• 文本生成器


    文本生成器

    要记住一点,\(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
  • 相关阅读:
    结构与联合
    信号与槽知识点
    函数
    元对象编译器moc
    堆与栈
    More Effective C++ (虚拟构造函数)
    重载 覆盖 隐藏
    继承专题
    PowerDesigner 的常用方法(转)
    搜狗输入法导入Google词库bug
  • 原文地址:https://www.cnblogs.com/cader/p/14666071.html
Copyright © 2020-2023  润新知