CF271D Good Substrings SAM

题意:

戳这里

分析:

建出SAM,然后 (dfs) 将不好字符的转移代价设置为 (1) ,好的字符的转移代价设置为 (0) 这样题意等价于求本质不同的长度小于等于 (k) 的字符串个数,(O(nk)) 的转移就行了

代码:

#include<bits/stdc++.h>

using namespace std;

namespace zzc
{
	inline int read()
	{
		int x=0,f=1;char ch=getchar();
		while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
		while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
		return x*f;
	}
    
    const int maxn = 1e4+5;
    int n,k;
    int f[maxn][1505];
    char ch[maxn];
    bool vis[maxn],chk[26];

    struct suffix_automaton
    {
        int cnt,lst;
        int link[maxn],trans[maxn][26],len[maxn];
        suffix_automaton(){cnt=lst=1;}

        void insert(int x)
        {
            int cur=++cnt,tmp=lst;lst=cnt;
            len[cur]=len[tmp]+1;
            for(;tmp&&!trans[tmp][x];tmp=link[tmp]) trans[tmp][x]=cur;
            if(!tmp)
            {
                link[cur]=1;
            }
            else
            {
                int q=trans[tmp][x];
                if(len[tmp]+1==len[q])
                {
                    link[cur]=q;
                }
                else
                {
                    int clone=++cnt;
                    len[clone]=len[tmp]+1;
                    link[clone]=link[q];
                    link[cur]=link[q]=clone;
                    for(int i=0;i<26;i++) trans[clone][i]=trans[q][i];
                    for(;tmp&&trans[tmp][x]==q;tmp=link[tmp]) trans[tmp][x]=clone;
                }
            }
        }
		
		void dfs(int u=1)
	    {
	        vis[u]=true;
	        for(int i=0;i<26;i++)
	        {
	            int v=trans[u][i];
	            if(!v) continue;
	            if(!vis[v]) dfs(v);
	            f[u][chk[i]]++;
	            for(int j=0;j<=k;j++) if(j-chk[i]>=0) f[u][j]+=f[v][j-chk[i]];
	        }
	    }
	
    }sam;

	void work()
	{
	    scanf("%s",ch+1);n=strlen(ch+1);
        for(int i=1;i<=n;i++) sam.insert(ch[i]-'a');
        scanf("%s",ch);
        for(int i=0;i<26;i++) chk[i]=(ch[i]=='0');
        k=read();
        sam.dfs();
        long long ans=0;
        for(int i=0;i<=k;i++) ans+=f[1][i];
        printf("%lld
",ans);
	}

}

int main()
{
	zzc::work();
	return 0;
}

原文地址:https://www.cnblogs.com/youth518/p/14221763.html