zoukankan      html  css  js  c++  java
  • 2781: [JSOI2007]文本生成器

    2781: [JSOI2007]文本生成器

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 8  Solved: 4
    [Submit][Status][Web Board]

    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的值

    Sample Input

    2 2
    A
    B

    Sample Output

    100  

    HINT

     

    Source

    题解:

      第一眼,Ac自动机。然后。。。。。。就JJ了,不知道怎么写了(QAQ)

      然后YY了半天总算有点点想法:我们直接计算的话,还真心有点小困难,所以怎么写呢?(龙老师:这,乱搞出奇迹,电脑砸了就好了!!!)

      额。。。。。。

      好吧,我们就算一下不可读的串数,总串数减去它就可以了。。。。。(龙老师:写什么写,乱搞出奇迹,War3飞起!!!)

      不可读的串的数量就是在AC自动机上走M步而不经过结尾节点(包括结尾点和fail指向结尾点的节点)的路径条数。

      这个怎么求呢?

      设f[i][j]表示走i步,现在在j号节点的路径条数。

      那么f[i][j]可以转移f[i+1][son[j][k]]。

      就是i+1个字符为k的状态。

      最后把所有f[m][i]累和就是不可读的串。(龙老师:说了吧,乱搞就写出来啦,还是我最吊!!!!)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int maxn=6000,maxm=105,mod=10007;
    using namespace std;
    int n,m,f[maxm][maxn],ans1=1,ans2; char s[maxn];
     
        int tot,son[maxn][26],fail[maxn],q[maxn],head,tail;bool dang[maxn];
        void insert(){
            int p=0,len=strlen(s);
            for (int i=0;i<len;p=son[p][s[i]-'A'],i++) if (!son[p][s[i]-'A']) son[p][s[i]-'A']=++tot;
            dang[p]=1;
        }
        void getfail(){
            head=0,q[tail=1]=0,fail[0]=-1;
            while (head!=tail){
                int x=q[++head];
                for (int i=0;i<26;i++)
                    if (son[x][i]) q[++tail]=son[x][i],fail[son[x][i]]=x==0?0:son[fail[x]][i];
                    else son[x][i]=x==0?0:son[fail[x]][i];
                dang[x]|=dang[fail[x]];
            }
        }
        void work(){
            f[0][0]=1;
            for (int i=1;i<=m;i++)
                for (int j=0;j<=tot;j++){
                    if (dang[j]) continue;
                    for (int k=0;k<26;k++)
                        f[i][son[j][k]]=(f[i][son[j][k]]+f[i-1][j])%mod;
                }
            for (int i=0;i<=tot;i++) if (!dang[i]) ans2+=f[m][i];
            for (int i=1;i<=m;i++) ans1=(ans1*26)%mod;
            printf("%d
    ",((ans1-ans2)%mod+mod)%mod);
        }
     
    int main(){
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%s",s),insert();
        getfail(),work();
        return 0;
    }
    View Code
  • 相关阅读:
    Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (gbk_chinese_ci,COERCIBLE) for operation '=' 一个解决办法(转载)
    mysql limit用法
    preparedStatement一个小技巧
    两个简单的压力测试代码。
    cookie实现session机制
    java.util.properties用法
    数据库是否使用外键,及视图,索引,存储过程的一些说明(zz)
    某项目要调用现有的100多个DLL 二 最最简单原型的思考
    面试题:红绿灯
    一个简单的封装 .net的日志功能
  • 原文地址:https://www.cnblogs.com/HQHQ/p/5368922.html
Copyright © 2011-2022 走看看