看到n<=20亿顿时傻眼。。AC自动机上用矩阵乘法优化DP。。。sxbk
建出AC自动机,把非法的节点去掉后求出trie图。。。
然后根据trie图中的转移关系建矩阵。。。。最后跑个快速幂
竟然搞出来了...感人肺腑
脑子各种短路。。先是矩乘打挂,然后是trie图求措TAT。调了一整节晚自修。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define ll long long 6 using namespace std; 7 const int modd=100000; 8 int v[257],dl[103],fail[103],num[103]; 9 int ch[103][4],tot,next[103][4]; 10 ll mp[103][103],cnt; 11 ll c[103][103],tmp[103][103],ans; 12 int i,j,k,n,m,l,r; 13 bool gg[103]; 14 char s[23]; 15 16 inline void trie(int n){ 17 int i,p=0; 18 for(i=0;i<n;i++){ 19 if(!ch[p][v[s[i]]])ch[p][v[s[i]]]=++tot,p=tot; 20 else p=ch[p][v[s[i]]]; 21 } 22 gg[p]=1;//printf("gg: %d\n",p); 23 } 24 inline void getfail(){ 25 int l=0,r=1,i,j,now,p;dl[1]=0; 26 while(l<r){ 27 now=dl[++l];//printf(" %d fail:%d gg:%d\n",now,fail[now],gg[now]); 28 for(i=0;i<4;i++)if(ch[now][i]){ 29 j=ch[now][i];//printf(" %d-->%d\n",now,j); 30 for(p=fail[now];p&&!ch[p][i];p=fail[p]); 31 if(!now)fail[j]=0;else fail[j]=ch[p][i]; 32 dl[++r]=j;gg[j]|=gg[fail[j]]; 33 } 34 } 35 } 36 inline void getnext(){ 37 l=0,r=1;int i,now,p;dl[1]=0; 38 bool flag=0; 39 while(l<r){ 40 now=dl[++l];//printf(" %d\n",now); 41 for(i=0;i<4;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<4;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;tmp[i][j]%=modd,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;tmp[i][j]%=modd,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 int main(){ 84 v[‘A‘]=0,v[‘C‘]=1,v[‘G‘]=2,v[‘T‘]=3; 85 86 scanf("%d%d",&n,&m); 87 for(i=1;i<=n;i++)scanf("%s",s),trie(strlen(s)); 88 getfail(),getnext(),upd(); 89 for(i=1;i<=cnt;i++)c[i][i]=1; 90 91 while(m){ 92 if(m&1) 93 multoc(); 94 m>>=1;if(m)multomp(); 95 } 96 for(i=1,ans=0;i<=cnt;i++)ans=(ans+c[i][1])%modd; 97 printf("%lld\n",ans); 98 return 0; 99 }
时间: 2024-10-20 22:44:16