1. 程式人生 > >[HNOI2008] GT考試

[HNOI2008] GT考試

前綴 close spa 矩陣乘法 pre 分享 方法 long %d

又是一道用KMP的字符串DP。

洛谷 P3193 傳送門

bzoj 1009 傳送門

設f[i][j]為主串匹配到第i位,模式串最多匹配到第j位的方案數。

令g[i][j]表示模式串的前綴i可以轉移到前綴j的方法數。

則:f[i][j]=(f[i-1][0]+f[i-1][1]+...+f[i-1][m-1])*g[k][j]。

用矩陣乘法優化一下遞推即可。

技術分享圖片
 1 #include<cstdio>
 2 
 3 int n,m,mod;
 4 char s[25];
 5 int nx[25];
 6 
 7 void getnx()
 8 {
 9     for(int i=2,j=1
;i<=m+1;) 10 { 11 nx[i]=j; 12 while(j&&s[i]!=s[j])j=nx[j]; 13 i++,j++; 14 } 15 } 16 17 struct matrix 18 { 19 int a[25][25]; 20 }f,g; 21 22 matrix multi(matrix q,matrix w) 23 { 24 matrix e; 25 for(int i=0;i<m;i++) 26 { 27 for(int j=0
;j<m;j++) 28 { 29 e.a[i][j]=0; 30 for(int k=0;k<m;k++) 31 { 32 e.a[i][j]=(e.a[i][j]+q.a[i][k]*w.a[k][j]%mod)%mod; 33 } 34 } 35 } 36 return e; 37 } 38 39 matrix ksm(matrix q,int t) 40 { 41 matrix ret=q; 42 t--;
43 while(t) 44 { 45 if(t&1)ret=multi(ret,q); 46 q=multi(q,q); 47 t>>=1; 48 } 49 return ret; 50 } 51 52 int main() 53 { 54 scanf("%d%d%d",&n,&m,&mod); 55 scanf("%s",s+1); 56 getnx(); 57 for(int i=0;i<m;i++) 58 { 59 for(int j=0;j<10;j++) 60 { 61 int p=i; 62 while(p&&s[p+1]!=j+0)p=nx[p+1]-1; 63 if(s[p+1]==j+0)p++; 64 if(p!=m)g.a[p][i]=(g.a[p][i]+1)%mod; 65 } 66 } 67 f=ksm(g,n); 68 long long ans=0; 69 for(int i=0;i<m;i++)ans=(ans+f.a[i][0])%mod; 70 printf("%lld",ans); 71 return 0; 72 }
GT考試

寫的時候,矩陣乘法忘打return了,調了半天都輸出0......

後來Dr_J幫我找出了這個沙雕錯誤......

[HNOI2008] GT考試