HDU 2243
//因为2^64次方不可能表示,直接定义unsigned __int64,可以自动截断。其他和POJ 2778差不多。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <climits> 6 #include <string.h> 7 #include <queue> 8 #include <cmath> 9 #include <vector> 10 #define LL unsigned __int64 11 using namespace std; 12 const int dictsize=26; 13 const int root=0; 14 const int QN=100; 15 struct Node{ 16 int fail,next[dictsize]; 17 bool tag; 18 void initial(){ 19 memset(next,-1,sizeof(next)); 20 tag=false,fail=-1; 21 } 22 }; 23 Node trie[50]; 24 int que[QN],head,tail,tot; 25 struct Matrix{ 26 LL mat[95][95]; 27 }a,per,number; 28 int n,l; 29 char str[20]; 30 31 void Insert_trie(){ 32 int p=root,i=0,index; 33 while(str[i]){ 34 index=str[i]-'a'; 35 if(trie[p].next[index]==-1){ 36 trie[p].next[index]=++tot; 37 } 38 p=trie[p].next[index]; 39 i++; 40 } 41 trie[p].tag=true; 42 } 43 44 void build_ac(){ 45 int p,tmp; 46 que[tail++]=root; 47 while(head!=tail){ 48 tmp=que[head++]; 49 p=-1; 50 for(int i=0;i<dictsize;i++){ 51 if(trie[tmp].next[i]!=-1){ 52 if(tmp==root) trie[trie[tmp].next[i]].fail=root; 53 else{ 54 p=trie[tmp].fail; 55 while(p!=-1){ 56 if(trie[p].next[i]!=-1){ 57 trie[trie[tmp].next[i]].fail=trie[p].next[i]; 58 break; 59 } 60 p=trie[p].fail; 61 } 62 if(p==-1) trie[trie[tmp].next[i]].fail=root; 63 } 64 if(trie[trie[trie[tmp].next[i]].fail].tag) 65 trie[trie[tmp].next[i]].tag=true; 66 que[tail++]=trie[tmp].next[i]; 67 } 68 else{ // tmp[tmp].next[i]==-1 69 if(tmp==root) trie[tmp].next[i]=root; 70 else{ 71 p=trie[tmp].fail; 72 while(p!=-1){ 73 if(trie[p].next[i]!=-1){ 74 trie[tmp].next[i]=trie[p].next[i]; 75 break; 76 } 77 p=trie[p].fail; 78 } 79 if(p==-1){ 80 trie[tmp].next[i]=root; 81 } 82 } 83 } 84 } 85 } 86 } 87 88 void build_map(){ 89 memset(a.mat,0,sizeof(a.mat)); 90 for(int i=0;i<=tot;i++){ 91 for(int j=0;j<dictsize;j++) 92 if(!trie[i].tag&&!trie[trie[i].next[j]].tag) 93 a.mat[i][trie[i].next[j]]++; 94 } 95 int tmp=2*tot+1; 96 for(int i=0;i<=tmp;i++){ 97 for(int j=tot+1;j<=tmp;j++){ 98 if(i==j) a.mat[i][j]=1; 99 else if(j-tot-1==i) a.mat[i][j]=1; 100 } 101 } 102 number.mat[0][0]=26,number.mat[0][1]=1; 103 number.mat[1][0]=0,number.mat[1][1]=1; 104 } 105 106 Matrix Multi(Matrix a,Matrix b,int e){ 107 Matrix c; 108 for(int i=0;i<=e;i++){ 109 for(int j=0;j<=e;j++){ 110 c.mat[i][j]=0; 111 for(int k=0;k<=e;k++) 112 c.mat[i][j]=(c.mat[i][j]+(a.mat[i][k]*b.mat[k][j])); 113 } 114 } 115 return c; 116 } 117 118 Matrix multi(Matrix s,LL k,int e){ 119 // cout<<k<<endl; 120 Matrix ret=per,p=s; 121 while(k){ 122 if(k&1) ret=Multi(ret,p,e); 123 k>>=1; 124 p=Multi(p,p,e); 125 } 126 return ret; 127 } 128 129 int main(){ 130 memset(per.mat,0,sizeof(per.mat)); 131 for(int i=0;i<95;i++) 132 per.mat[i][i]=1LL; 133 while(scanf("%d%d",&n,&l)!=EOF){ 134 for(int i=0;i<35;i++) 135 trie[i].initial(); 136 tot=head=tail=0; 137 for(int i=1;i<=n;i++){ 138 scanf("%s",str); 139 Insert_trie(); 140 } 141 build_ac(); 142 build_map(); 143 // cout<<tot<<endl; 144 Matrix n1=multi(number,(LL)l+1LL,1); 145 Matrix n2=multi(a,(LL)l+1LL,2*tot+1); 146 LL ans=n1.mat[0][1]; 147 // cout<<ans<<endl; 148 /* for(int i=0;i<=2*tot+1;i++){ 149 for(int j=0;j<=2*tot+1;j++) 150 cout<<a.mat[i][j]<<" "; 151 cout<<endl; 152 }*/ 153 int tmp=2*tot+1; 154 for(int i=tot+1;i<=tmp;i++) 155 ans=(ans-n2.mat[0][i]); 156 printf("%I64u\n",ans); 157 } 158 }