bzoj1030 [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的值。

Sample Input

2 2
A
B

Sample Output

100

 

正解:$AC$自动机+$DP$。

首先我们构造好$AC$自动机,并且记录一下每一位是否可能形成匹配,就是记录每一位的$val$和$last$就行了。

设$f[i][j]$表示统计到文本前$i$位,自动机上第$j$位,没有匹配的方案数,去掉能匹配的情况,直接大力转移就行了。

最后我们再用总方案数减去不匹配的方案数,就是至少有一个匹配的方案数。

 

  1 //It is made by wfj_2048~
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <complex>
  5 #include <cstring>
  6 #include <cstdlib>
  7 #include <cstdio>
  8 #include <vector>
  9 #include <cmath>
 10 #include <queue>
 11 #include <stack>
 12 #include <map>
 13 #include <set>
 14 #define rhl (10007)
 15 #define inf (1<<30)
 16 #define N (10010)
 17 #define il inline
 18 #define RG register
 19 #define ll long long
 20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
 21 
 22 using namespace std;
 23 
 24 int f[110][N],q[N],n,m,len,ans;
 25 char s[N];
 26 
 27 struct AC_auto{
 28 
 29     int ch[N][26],val[N],nxt[N],last[N],sz;
 30 
 31     il void insert(char *s,RG int len){
 32     RG int x=0,c;
 33     for (RG int i=1;i<=len;++i){
 34         c=s[i]-65;
 35         if (!ch[x][c]) ch[x][c]=++sz;
 36         x=ch[x][c];
 37     }
 38     val[x]++; return;
 39     }
 40     
 41     il void build(){
 42     RG int h=0,t=0;
 43     for (RG int c=0;c<26;++c)
 44         if (ch[0][c]) nxt[ch[0][c]]=last[ch[0][c]]=0,q[++t]=ch[0][c];
 45     while (h<t){
 46         RG int x=q[++h],v,j;
 47         for (RG int c=0;c<26;++c){
 48         v=ch[x][c]; if (!v){ ch[x][c]=ch[nxt[x]][c]; continue; }
 49         q[++t]=v,nxt[v]=last[v]=0,j=nxt[x]; while (j && !ch[j][c]) j=nxt[j];
 50         nxt[v]=ch[j][c],last[v]=val[nxt[v]] ? nxt[v] : last[nxt[v]];
 51         }
 52     }
 53     return;
 54     }
 55     
 56 }AC;
 57 
 58 il int gi(){
 59     RG int x=0,q=1; RG char ch=getchar();
 60     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
 61     if (ch=='-') q=-1,ch=getchar();
 62     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
 63     return q*x;
 64 }
 65 
 66 il int qpow(RG int a,RG int b){
 67     RG int ans=1;
 68     while (b){
 69     if (b&1) ans=ans*a%rhl;
 70     a=a*a%rhl,b>>=1;
 71     }
 72     return ans;
 73 }
 74 
 75 il void work(){
 76     n=gi(),m=gi();
 77     for (RG int i=1;i<=n;++i){
 78     scanf("%s",s+1);
 79     len=strlen(s+1);
 80     AC.insert(s,len);
 81     }
 82     AC.build(); f[0][0]=1;
 83     for (RG int i=0;i<m;++i)
 84     for (RG int j=0;j<=AC.sz;++j){
 85         if (!f[i][j]) continue;
 86         for (RG int k=0;k<26;++k){
 87         if (AC.val[AC.ch[j][k]] || AC.last[AC.ch[j][k]]) continue;
 88         f[i+1][AC.ch[j][k]]+=f[i][j];
 89         if (f[i+1][AC.ch[j][k]]>=rhl) f[i+1][AC.ch[j][k]]-=rhl;
 90         }
 91     }
 92     for (RG int i=0;i<=AC.sz;++i){ ans+=f[m][i]; if (ans>=rhl) ans-=rhl; }
 93     printf("%d\n",(qpow(26,m)-ans+rhl)%rhl); return;
 94 }
 95 
 96 int main(){
 97     File("txt");
 98     work();
 99     return 0;
100 }

 

posted @ 2017-04-13 10:39  wfj_2048  阅读(203)  评论(0编辑  收藏  举报