[AC自动机+DP]BZOJ1030 (JSOI2007)文本生成器 题解

版权声明:本文为博主原创文章,欢迎转载。 https://blog.csdn.net/try__jhf/article/details/82503119

题目大意

给出n个模板串,如果在一个文本中至少存在一个模板串,那么这个文本就是合法的,求长度为m的文本的合法方案数模10007后的结果。

解题报告

AC自动机+DP的经(mo)典(ban)题。正难则反,答案为 26 m 减去一个都匹配不到的方案。用模板串建AC自动机, f [ i ] [ j ] 表示文本串长度为 i ,在AC自动机上匹配到节点 j 的方案数,注意别走到单词节点,而且如果 f a i l [ x ] 是匹配的话,那么x也匹配。构造fail函数时加一道就行了。

示例代码

#include<cstdio>
#include<cstring>
using namespace std;
const int tt=10007;
int n,k,len,ans,ch[6005][26],nxt[6005],lst[6005],que[6005],f[105][6005];
bool vs[6005];
char s[105];
struct AC{
    void clear(int x){memset(ch[x],0,sizeof(ch[x])); nxt[x]=lst[x]=0;}
    void insist(){
        int now=0,L=strlen(s);
        for (int i=0;i<L;i++){
            if (!ch[now][s[i]-'A']) {ch[now][s[i]-'A']=++len; clear(len);}
            now=ch[now][s[i]-'A'];
        }
        vs[now]=1;
    }
    void makeF(){
        int hed=0,til=0;
        for (int i=0;i<26;i++)
            if (ch[0][i]){
                que[++til]=ch[0][i];
                nxt[ch[0][i]]=lst[ch[0][i]]=0;
            }
        while (hed!=til){
            int x=que[++hed]; vs[x]|=vs[nxt[x]];
            for (int i=0;i<26;i++)
                if (ch[x][i]){
                    int now=ch[x][i]; nxt[now]=ch[nxt[x]][i];
                    lst[now]=(vs[nxt[now]])?nxt[now]:lst[nxt[now]];
                    que[++til]=now;
                }else ch[x][i]=ch[nxt[x]][i];
        }
    }
}tr;
int main()
{
    freopen("text.in","r",stdin);
    freopen("text.out","w",stdout);
    scanf("%d%d",&n,&k); len=0; memset(vs,0,sizeof(vs));
    for (int i=1;i<=n;i++) {scanf("%s",s); tr.insist();}
    tr.makeF(); memset(f,0,sizeof(f)); f[0][0]=1;
    for (int i=0;i<k;i++)
        for (int j=0;j<=len;j++)
            if (f[i][j]&&!vs[j])
                for (int t=0;t<26;t++)
                    if (!vs[ch[j][t]]) f[i+1][ch[j][t]]=(f[i+1][ch[j][t]]+f[i][j])%tt;
    ans=1; for (int i=1;i<=k;i++) ans=(ans*26)%tt;
    for (int i=0;i<=len;i++) if (!vs[i]) ans=(ans+tt-f[k][i])%tt;
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/try__jhf/article/details/82503119