• BZOJ 1030 【JSOI2007】 文本生成器


    Description

      JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,
    他们现在使用的是GW文本生成器v6版。该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文
    章—— 也就是说,生成的文章中每个字节都是完全随机的。如果一篇文章中至少包含使用者们了解的一个单词,
    那么我们说这篇文章是可读的(我们称文章a包含单词b,当且仅当单词b是文章a的子串)。但是,即使按照这样的
    标准,使用者现在使用的GW文本生成器v6版所生成的文章也是几乎完全不可读的?。ZYX需要指出GW文本生成器 v6
    生成的所有文本中可读文本的数量,以便能够成功获得v7更新版。你能帮助他吗?

    Input

      输入文件的第一行包含两个正整数,分别是使用者了解的单词总数N (<= 60),GW文本生成器 v6生成的文本固
    定长度M;以下N行,每一行包含一个使用者了解的单词。这里所有单词及文本的长度不会超过100,并且只可能包
    含英文大写字母A..Z

    Output

      一个整数,表示可能的文章总数。只需要知道结果模10007的值。

     
      像我这样成天刷水题吃枣药丸
      这道题就是问有多少个 包含至少一个给定串,并且长度为$m$的串。然后,显然这种多串处理的题是要AC自动机的。构出AC自动机后在上面dp就可以了。
      其实感觉直接dp也可以做,但其实把问题转化一下更好做。求出所有不合法的串然后用总数量减一下就可以了。于是$f_{i,j}$表示在AC自动机上走了$i$步后到达节点$j$的方案数,转移的时候不经过单词的结束节点即可。
      AC自动机都写错的我吃枣药丸
      下面贴代码:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    #define maxn 6010
    #define mod 10007
     
    using namespace std;
    typedef long long llg;
     
    int n,m,fl[maxn],d[maxn],ans;
    int ch[maxn][26],sz,f[101][maxn];
    bool val[maxn],w[maxn];
     
    int getint(){
        int w=0;bool q=0;
        char c=getchar();
        while((c>'9'||c<'0')&&c!='-') c=getchar();
        if(c=='-') c=getchar(),q=1;
        while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
        return q?-w:w;
    }
     
    void gi(int &x){if(x>=mod) x%=mod;}
    void insert(){
        char c=getchar();
        while(c>'Z'||c<'A') c=getchar();
        int u=0;
        while(c>='A' && c<='Z'){
            if(!ch[u][c-'A']) ch[u][c-'A']=++sz;
            u=ch[u][c-'A']; c=getchar();
        }
        val[u]=1;
    }
     
    void getf(){
        int l=0,r=0,u;d[r++]=0;
        while(l!=r){
            u=d[l++];
            for(int i=0,j;i<26;i++)
                if(ch[u][i]){
                    j=fl[u];
                    while(!ch[j][i] && j) j=fl[j];
                    if(u!=j){
                        fl[ch[u][i]]=ch[j][i];
                        val[ch[u][i]]|=val[ch[j][i]];
                    }
                    d[r++]=ch[u][i];
                }
                else ch[u][i]=ch[fl[u]][i];
        }
    }
     
    int main(){
        File("a");
        n=getint(); m=getint();
        while(n--) insert();
        getf(); f[0][0]=ans=1;
        for(int i=0;i<m;i++)
            for(int u=0;u<=sz;u++)
                if(!val[u])
                    for(int j=0;j<26;j++)
                        f[i+1][ch[u][j]]+=f[i][u],gi(f[i+1][ch[u][j]]);
        for(int i=1;i<=m;i++) ans*=26,gi(ans);
        for(int u=0;u<=sz;u++) if(!val[u]) ans-=f[m][u],ans+=mod,gi(ans);
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    使用pjsip传输已经编码的视频
    xubuntu14.04下编译pjsip及pjsua2 java
    解决 Python.h:没有那个文件或目录 错误的方法
    HIbernate與不支持boolean的數據庫之間的映射
    js数组的操作
    jQuery中ajax的使用与缓存问题的解决方法
    网络游戏中应用可插拔工厂处理消息
    How to Train Triplet Networks with 100K Identities?
    (转)如何用TensorLayer做目标检测的数据增强
    图像超分辨-IDN
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/6009551.html
Copyright © 2020-2023  润新知