文本生成器

文本生成器

要记住一点,\(next[now][c]\)指向的是在\(now\)指向的这一节点所表示的字符串\(S\)再添加一个字母\(c\)所能形成的字符串。有两种可能,①存在\(S’=S+c\),②存在\(S'\)\(S+c\)的最长真后缀,也就是说,要再目标串中看有多少模式串,只需要在遍历目标串的时候无脑往后面加字符\(c\)就好了,如果\(end[next[now][c]]\)不为0,则证明出现了\(next[now][c]\)所表示的字符串,而此时不管是情况①,还是情况②,都是表示某个模式串出现了。

// Created by CAD
#include <bits/stdc++.h>

using namespace std;
const int maxn=6005;
const int mod=1e4+7;
struct AC{
    int next[maxn][30],fail[maxn],end[maxn];
    int root,L;
    int newnode(){
        for(int i=0;i<26;++i)
            next[L][i]=-1;
        end[L++]=0;
        return L-1;
    }
    void init(){
        L=0;
        root=newnode();
    }
    void insert(char buf[]){
        int len=strlen(buf);
        int now=root;

        for(int i=0;i<len;++i){
            int c=buf[i]-'A';
            if(next[now][c]==-1)
                next[now][c]=newnode();
                now=next[now][c];
        }
        end[now]++;
    }
    void build(){
        queue<int> Q;
        fail[root]=root;
        for(int i=0;i<26;++i){
            if(next[root][i]==-1)
                next[root][i]=root;
            else {
                fail[next[root][i]]=root;
                Q.push(next[root][i]);
            }
        }
        while(!Q.empty()){
            int now=Q.front();Q.pop();
            if(end[fail[now]]) end[now]=1;
            for(int i=0;i<26;++i){
                if(next[now][i]==-1)
                    next[now][i]=next[fail[now]][i];
                else {
                    fail[next[now][i]]=next[fail[now]][i];
                    Q.push(next[now][i]);
                }
            }
        }
    }
};
char buf[maxn];
int dp[105][maxn];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m;cin>>n>>m;
    AC ac;
    ac.init();
    for(int i=1;i<=n;++i)
        cin>>buf,ac.insert(buf);
    ac.build();
    dp[0][0]=1;
    int ans=1;
    for(int i=1;i<=m;++i){
        for(int j=0;j<ac.L;++j){
            for(int k=0;k<26;++k){
                if(!ac.end[ac.next[j][k]]){
                    (dp[i][ac.next[j][k]]+=dp[i-1][j ])%=mod;
                }
            }
        }
        (ans*=26)%=mod;
    }

    for(int i=0;i<ac.L;++i)
        (ans-=dp[m][i])%=mod;
    cout<<(ans+mod)%mod<<endl;
    return 0;
}
CAD加油!欢迎跟我一起讨论学习算法,QQ:1401650042
原文地址:https://www.cnblogs.com/cader/p/14666071.html