1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 using namespace std;
 5 char ch[105],s[106];
 6 int n,m,a[6007][27],size=1,fail[6007],dui[6007],b[101][6007],sum,sum1;
 7 bool f[6007];
 8 void jia()
 9 {
10     int now=1,l=strlen(ch);
11     for(int i=0;i<l;i++)
12       {
13         int t=ch[i]-'A'+1;
14         if(a[now][t])
15           now=a[now][t];
16         else
17           {
18             size++;
19             now=a[now][t]=size;
20           }
21       }
22     f[now]=1;
23 }
24 void shi()
25 {
26     int t=1,h=0;
27     dui[1]=1;
28     for(;h<t;)
29       {
30         int k=dui[++h];
31         for(int i=1;i<=26;i++)
32           if(a[k][i])
33             {
34                 int x=fail[k];
35                 for(;!a[x][i];x=fail[x]);
36                 fail[a[k][i]]=a[x][i];
37                 if(f[a[x][i]])
38                   f[a[k][i]]=1;
39                 dui[++t]=a[k][i];
40               }
41       }
42 }
43 void dp(int a1)
44 {
45     for(int i=1;i<=size;i++)
46       {
47         if(f[i]||!b[a1-1][i])
48           continue;
49         for(int j=1;j<=26;j++)
50           {
51             int k=i;
52             for(;!a[k][j];k=fail[k]);
53               b[a1][a[k][j]]=(b[a1][a[k][j]]+b[a1-1][i])%10007;
54           }
55       }
56 }
57 int main()
58 {
59     for(int i=1;i<=26;i++)
60       a[0][i]=1;
61     scanf("%d%d",&n,&m);
62     for(int i=0;i<n;i++)
63       {
64         scanf("%s",ch);
65         jia();
66       }
67     shi();
68     b[0][1]=1;
69     for(int i=1;i<=m;i++)
70       dp(i);
71     sum=1;
72     for(int i=1;i<=m;i++)
73       sum=(sum*26)%10007;
74     for(int i=1;i<=size;i++)
75       if(!f[i])
76       sum1=(sum1+b[m][i])%10007;
77     printf("%d\n",(sum-sum1+10007)%10007);
78     return 0;
79 }

AC自动机 将所有单词读入建出AC自动机,再在fail树上跑即可,用总可能数减去没有单词的数,没有单词的数用dp求,b[i][j]是第i个字符匹配到AC自动机上的j节点

posted on 2016-02-29 22:49  xiyuedong  阅读(88)  评论(0编辑  收藏