【bzoj1009】: [HNOI2008]GT考试 字符串-kmp-矩阵乘法-DP

【bzoj1009】: [HNOI2008]GT考试

先用kmp写个暴力

 1 /* http://www.cnblogs.com/karl07/ */
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <algorithm>
 7 using namespace std;
 8 char s[25];
 9 int n,m,p,fail[25],f[1000][25];
10 
11 void kmp(){
12     fail[1]=0;
13     for (int i=2;i<=m;i++){
14         fail[i]=fail[i-1];
15         if (s[fail[i-1]]==s[i-1]) fail[i-1]=fail[fail[i-1]];
16         while (s[fail[i]]!=s[i-1] && fail[i]) fail[i]=fail[fail[i]];
17         fail[i]++;
18     }
19 }
20 
21 int main(){
22     scanf("%d%d%d",&n,&m,&p);
23     scanf("%s",s+1);
24     kmp();
25     f[0][0]=1;
26     for (int i=1;i<=n;i++){
27         for (int j=0;j<m;j++){
28             for (int k='0',now=j+1;k<='9';k++,now=j+1){
29                 while (k!=s[now] && now) now=fail[now];
30                 f[i][now]=(f[i][now]+f[i-1][j])%p;
31             }
32         }
33     }
34     int ans=0;
35     for (int i=0;i<m;i++){
36         ans=(ans+f[n][i])%p;
37     }
38     printf("%d\n",ans);
39     return 0;
40 }
暴力

然后对着转移方程yy一下矩阵就好辣

 1 /* http://www.cnblogs.com/karl07/ */
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <algorithm>
 7 using namespace std;
 8 char s[25];
 9 int n,m,p,fail[25];
10 struct MAT{
11     int m[25][25];
12     int x,y;
13 }m1,m2;
14 
15 MAT operator * (const MAT &a,const MAT &b){
16     MAT c;
17     c.x=b.x,c.y=a.y;
18     for (int i=1;i<=c.x;i++){
19         for (int j=1;j<=c.y;j++){
20             c.m[i][j]=0;
21             for (int k=1;k<=b.y;k++){
22                 c.m[i][j]=(c.m[i][j]+a.m[k][j]*b.m[i][k])%p;
23             }
24         }
25     } 
26     return c;
27 }
28 
29 int sum(MAT a){
30     int ans=0;
31     for (int i=1;i<=a.x;i++){
32         for (int j=1;j<=a.y;j++){
33             ans=(ans+a.m[i][j])%p;
34         }
35     }
36     return ans;
37 }
38 
39 void kmp(){
40     fail[1]=0;
41     for (int i=2;i<=m;i++){
42         fail[i]=fail[i-1];
43         if (s[fail[i-1]]==s[i-1]) fail[i-1]=fail[fail[i-1]];
44         while (s[fail[i]]!=s[i-1] && fail[i]) fail[i]=fail[fail[i]];
45         fail[i]++;
46     }
47 }
48 
49 MAT qpow(int x){
50     for (;x;x=(x>>1),m2=m2*m2) if (x&1) m1=m1*m2;
51     return m1;
52 }
53 
54 int main(){
55     scanf("%d%d%d",&n,&m,&p);
56     scanf("%s",s+1);
57     kmp();
58     m1.x=m;m1.y=1;m1.m[1][1]=1;
59     m2.x=m2.y=m;
60     for (int i=2;i<=m;i++) m1.m[i][1]=0;
61     for (int i=1;i<=m;i++) for (int j=1;j<=m;j++) m2.m[i][j]=0;
62     for (int j=0;j<m;j++){
63         for (int k='0',now=j+1;k<='9';k++,now=j+1){
64             while (k!=s[now] && now)now=fail[now]; 
65             m2.m[now+1][j+1]++;
66         }
67     }
68     printf("%d\n",sum(qpow(n)));
69     return 0;
70 }
正解

 为什么感觉自己的kmp写的好奇怪。。

posted @ 2017-04-02 04:06  karl07  阅读(228)  评论(0编辑  收藏  举报