标签:
又是AC自动机上用矩乘优化DP= =
其实和上一题基本一样。。。补集转化思想。。
只是要多弄一个小矩阵求(26^1+26^2+....+26^L),并且也要求f的总和(因为是长度<=L)
直接调上一题的伪板子了= =
喜闻乐见CE了好几发。。。就因为iostream里有next这个名字的函数>_<(那我上一题怎么没CE啊摔
1 #include<cstdio> 2 #include<cstring> 3 #define ll long long 4 #define ull unsigned long long 5 using namespace std; 6 int dl[33],fail[33],num[33]; 7 int ch[33][26],tot,next[33][26]; 8 ull mp[36][36]; 9 ull c[36][36],tmp[36][36],ans; 10 int i,j,k,n,m,l,r,cnt; 11 bool gg[103]; 12 char s[23]; 13 14 ll tm[103],t[103]; 15 16 inline void trie(int n){ 17 int i,p=0; 18 for(i=0;i<n;i++){ 19 s[i]-=‘a‘; 20 if(!ch[p][s[i]])ch[p][s[i]]=++tot,p=tot; 21 else p=ch[p][s[i]]; 22 } 23 gg[p]=1;//printf("gg: %d\n",p); 24 } 25 inline void getfail(){ 26 int l=0,r=1,i,j,now,p;dl[1]=0; 27 while(l<r){ 28 now=dl[++l];//printf(" %d fail:%d gg:%d\n",now,fail[now],gg[now]); 29 for(i=0;i<26;i++)if(ch[now][i]){ 30 j=ch[now][i];//printf(" %d-->%d\n",now,j); 31 for(p=fail[now];p&&!ch[p][i];p=fail[p]); 32 if(!now)fail[j]=0;else fail[j]=ch[p][i]; 33 dl[++r]=j;gg[j]|=gg[fail[j]]; 34 } 35 } 36 } 37 inline void getnext(){ 38 l=0,r=1;int i,now,p;dl[1]=0; 39 while(l<r){ 40 now=dl[++l];//printf(" %d\n",now); 41 for(i=0;i<26;i++){ 42 if(ch[now][i]){ 43 if(gg[ch[now][i]])next[now][i]=-1; 44 else next[now][i]=ch[now][i],dl[++r]=ch[now][i]; 45 } 46 else{ 47 for(p=fail[now];p&&!ch[p][i];p=fail[p]); 48 next[now][i]=gg[ch[p][i]]?-1:ch[p][i]; 49 } 50 // printf("%d %d next:%d\n",now,i,next[now][i]); 51 } 52 } 53 } 54 inline void upd(){ 55 cnt=0;int i,j; 56 for(i=1;i<=r;i++) 57 num[dl[i]]=++cnt; 58 for(i=1;i<=r;i++){ 59 j=dl[i]; 60 for(k=0;k<26;k++)if(next[j][k]!=-1) 61 mp[num[next[j][k]]][num[j]]++; 62 } 63 64 // for(i=1;i<=r;puts(""),i++) 65 // for(j=1;j<=r;j++)printf(" %lld",mp[i][j]); 66 } 67 68 69 inline void multoc(){ 70 register int i,j,k; 71 for(i=1;i<=cnt;i++) 72 for(j=1;j<=cnt;j++) 73 for(tmp[i][j]=0,k=1;k<=cnt;k++)tmp[i][j]+=mp[i][k]*c[k][j]; 74 for(i=1;i<=cnt;i++)memcpy(c[i],tmp[i],(cnt+1)<<3); 75 } 76 inline void multomp(){ 77 register int i,j,k; 78 for(i=1;i<=cnt;i++) 79 for(j=1;j<=cnt;j++) 80 for(tmp[i][j]=0,k=1;k<=cnt;k++)tmp[i][j]+=mp[i][k]*mp[k][j]; 81 for(i=1;i<=cnt;i++)memcpy(mp[i],tmp[i],(cnt+1)<<3); 82 } 83 84 int main(){ 85 while(scanf("%d%d",&n,&m)!=EOF){ 86 for(i=1;i<=n;i++)scanf("%s",s),trie(strlen(s)); 87 getfail(),getnext(),upd(); 88 cnt++; 89 for(i=1;i<=cnt;i++)mp[cnt][i]=1; 90 cnt++,mp[cnt][cnt]=26,cnt++,mp[cnt][cnt-1]=mp[cnt][cnt]=1; 91 92 // for(i=1;i<=cnt;puts(""),i++)for(j=1;j<=cnt;j++)printf(" %llu",mp[i][j]); 93 94 for(i=1;i<=cnt;i++)c[i][i]=1; 95 96 /* tm[1]=1; 97 for(i=1;i<=m;i++){ 98 for(j=1;j<=cnt;j++) 99 for(k=1,t[j]=0;k<=cnt;k++)t[j]=(t[j]+mp[j][k]*tm[k])%modd; 100 memcpy(tm,t,sizeof(t)); 101 }*/ 102 103 while(m){ 104 if(m&1) 105 multoc(); 106 m>>=1;if(m)multomp(); 107 // for(i=1;i<=cnt;puts(""),i++)for(j=1;j<=cnt;j++)printf(" %llu",c[i][j]); 108 } 109 110 // for(i=1;i<=cnt;puts(""),i++)for(j=1;j<=cnt;j++)printf(" %llu",c[i][j]); 111 //for(i=1,ans=0;i<=cnt;i++)ans=(ans+c[i][1])%modd; 112 ull ans=c[cnt][cnt-1]*26; 113 for(i=1;i<=cnt-2;i++)ans-=c[i][1]; 114 printf("%I64u\n",ans+1); 115 116 memset(mp,0,sizeof(mp)),memset(c,0,sizeof(c)), 117 memset(ch,0,(tot+1)*4*26),memset(next,0,(tot+1)*4*26),memset(fail,0,(tot+1)<<2),memset(gg,0,tot+1),tot=0; 118 } 119 // for(i=1,ans=0;i<=cnt;i++)ans=(ans+tm[i])%modd; 120 // printf("%lld\n",ans); 121 return 0; 122 }
标签:
原文地址:http://www.cnblogs.com/czllgzmzl/p/5335028.html