[JSOI2007]文本生成器

题目描述

JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版。

该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文章—— 也就是说,生成的文章中每个字节都是完全随机的。如果一篇文章中至少包含使用者们了解的一个单词,那么我们说这篇文章是可读的(我们称文章a包含单词b,当且仅当单词b是文章a的子串)。但是,即使按照这样的标准,使用者现在使用的GW文本生成器v6版所生成的文章也是几乎完全不可读的?。ZYX需要指出GW文本生成器 v6

生成的所有文本中可读文本的数量,以便能够成功获得v7更新版。你能帮助吗?

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1: 复制
2 2
A
B
输出样例#1: 复制
100
令f[i][j]表示文章长度为i,在AC自动机位置为j没有单词的方案数
然后答案就是26m-∑f[m][]
转移就是从AC自动机往下走
f[i+1][ch[j][k]]+=f[i][j] (ch[j][k]位置没有标记)
注意处理AC自动机时,处理包含的情况
val[x]|=val[fail[x]]
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 queue<int>Q;
 9 int ch[10010][27],f[110][10010],size,val[10010],fail[10010],n,m,Mod=10007,ans;
10 char s[110];
11 int qpow(int x,int y)
12 {
13   int res=1;
14   while (y)
15     {
16       if (y&1) res=1ll*res*x%Mod;
17       x=1ll*x*x%Mod;
18       y>>=1;
19     }
20   return res;
21 }
22 void insert(int len)
23 {int i;
24   int now=0;
25   for (i=0;i<len;i++)
26     {
27       if (ch[now][s[i]-'A']==0)
28     ch[now][s[i]-'A']=++size;
29       now=ch[now][s[i]-'A'];
30     }
31   val[now]=1;
32 }
33 void AC_build()
34 {int i;
35   for (i=0;i<26;i++)
36     if (ch[0][i])
37       fail[ch[0][i]]=0,Q.push(ch[0][i]);
38   while (Q.empty()==0)
39     {
40       int u=Q.front();
41       Q.pop();
42       for (i=0;i<26;i++)
43     {
44       if (ch[u][i]) fail[ch[u][i]]=ch[fail[u]][i],Q.push(ch[u][i]);
45       else ch[u][i]=ch[fail[u]][i];
46       if (val[fail[u]])
47         val[u]=val[fail[u]];
48     }
49     }
50 }
51 int main()
52 {int i,j,k,len;
53   cin>>n>>m;
54   for (i=1;i<=n;i++)
55     {
56       scanf("%s",s);
57       len=strlen(s);
58       insert(len);
59     }
60   AC_build();
61   f[0][0]=1;
62   for (i=0;i<m;i++)
63     {
64       for (j=0;j<=size;j++)
65     if (f[i][j]&&val[j]==0)
66     {
67       for (k=0;k<26;k++)
68         {
69           f[i+1][ch[j][k]]+=f[i][j];
70           if (f[i+1][ch[j][k]]>=Mod) f[i+1][ch[j][k]]-=Mod;
71         }
72     }
73     }
74   for (i=0;i<=size;i++)
75     if (val[i]==0)
76     {
77       ans+=f[m][i];
78       if (ans>=Mod) ans-=Mod;
79     }
80   cout<<(qpow(26,m)-ans+Mod)%Mod;
81 }

 

posted @ 2018-02-12 14:50  Z-Y-Y-S  阅读(354)  评论(0编辑  收藏  举报