zoukankan      html  css  js  c++  java
  • bzoj 1030 AC自动机+dp

    代码:

    //先把给的单词建AC自动机并且转移fail,然后d[i][j]表示构造的文章到第i位时处在字典树的第j个节点的不包含单词的数量,最后用总的数量26^m
    //-d[m][0~sz]即可。其中不能走单词结尾的节点以及他们的fail。这里其实要把每个节点都连向他的26个后继,但是不连也没关系可以看作
    //那些没出现的节点都转移成了0节点。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int MAXN=6009;
    const int MOD=10007;
    int node[MAXN][30],val[MAXN],f[MAXN],sz,d[109][MAXN];
    char s[109];
    int n,m;
    void init()
    {
        sz=0;
        memset(node[0],0,sizeof(node[0]));
        val[0]=f[0]=0;
        memset(d,0,sizeof(d));
    }
    void insert(char *s)
    {
        int len=strlen(s),rt=0;
        for(int i=0;i<len;i++){
            int id=s[i]-'A';
            if(!node[rt][id]){
                node[rt][id]=++sz;
                memset(node[sz],0,sizeof(node[sz]));
                val[sz]=0;
            }
            rt=node[rt][id];
        }
        val[rt]=1;
    }
    void get_fail()
    {
        queue<int>q;
        for(int i=0;i<26;i++){
            int u=node[0][i];
            if(u) { q.push(u);f[u]=0; }
        }
        while(!q.empty()){
            int rt=q.front();q.pop();
            for(int i=0;i<26;i++){
                int u=node[rt][i];
                if(!u){
                    node[rt][i]=node[f[rt]][i];
                    continue;
                }
                q.push(u);
                f[u]=node[f[rt]][i];
            }
            val[rt]|=val[f[rt]];
        }
    }
    void get_d()
    {
        d[0][0]=1;
        for(int i=1;i<=m;i++){
            for(int j=0;j<=sz;j++){
                if(val[j]||d[i-1][j]==0) continue;
                for(int k=0;k<26;k++)if(!val[node[j][k]])
                    d[i][node[j][k]]=(d[i][node[j][k]]+d[i-1][j])%MOD;
            }
        }
    }
    int main()
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++){
            scanf("%s",s);
            insert(s);
        }
        get_fail();
        get_d();
        int ans1=0,ans2=1;
        for(int i=0;i<=sz;i++)if(!val[i])
            ans1=(ans1+d[m][i])%MOD;
        for(int i=1;i<=m;i++)
            ans2=(ans2*26)%MOD;
        printf("%d
    ",(ans2+MOD-ans1)%MOD);
        return 0;
    }
  • 相关阅读:
    Input file 调用相机
    C#读取txt文件
    高并发下获取随机字符串
    将Datatable转换为Json数据
    System.IO.Path 获得文件的后缀名
    用Js写的贪吃蛇游戏
    C#中的事件
    通过一个控制台小Demo--算术题,来展示C#基本的程序结构
    数据库高级应用之游标
    数据库高级应用之事务
  • 原文地址:https://www.cnblogs.com/--ZHIYUAN/p/7613945.html
Copyright © 2011-2022 走看看