BZOJ--1009(KMP,DP,矩阵快速幂)

2014-12-15 22:25:47

思路:这题写了我好久,主要是卡在根据KMP结果来构造矩阵上面。

  如果用dp[i][j]表示用前i个字符匹配字串前j个字符

  那么考虑用i->i+1的转移。

  显然,如果考虑所有i+1位可能放的数字(0~9)

  那么有:dp[i+1][j+1] += dp[i][j] //继续匹配下一个字符(j+1)

      dp[i+1][0] += dp[i][j] //字串根本无法匹配

      dp[i+1][1] += dp[i][j] //刚好能匹配字串的第一个字符

      dp[i+1][P[j]+1] += dp[i][j] //根据KMP,如果i+1位置失效,那么往前找最近的匹配位置!

  那么根据转移方程来构造矩阵,快速幂即可。(因为可以0匹配,所以KMP构造P数组的时候要注意下标起点(最好字串从1下标开始))

 1 /*************************************************************************
 2     > File Name: b1009.cpp
 3     > Author: Natureal
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Mon 15 Dec 2014 08:32:47 PM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 typedef unsigned long long ull;
26 const int INF = 1 << 30;
27 
28 int N,M,K;
29 int P[30];
30 char s[30];
31 
32 struct Mx{
33     int a[30][30];
34     void clear(){ memset(a,0,sizeof(a));}
35     void stand(){ clear(); for(int i = 0; i < 20; ++i) a[i][i] = 1;}
36     Mx operator * (Mx b){
37         Mx c; c.clear();
38         for(int i = 0; i < 20; ++i)
39         for(int j = 0; j < 20; ++j)
40         for(int k = 0; k < 20; ++k){
41             c.a[i][j] = (c.a[i][j] + a[i][k] * b.a[k][j]) % K;
42         }
43         return c;
44     }
45 };
46 
47 void Get_P(){
48     P[1] = 0;
49     int j = 0;
50     for(int i = 2; i <= M; ++i){
51         while(j > 0 && s[j + 1] != s[i]) j = P[j];
52         if(s[j + 1] == s[i]) j++;
53         P[i] = j;
54     }
55 }
56 
57 int main(){
58     scanf("%d%d%d",&N,&M,&K);
59     scanf("%s",s + 1);
60     Get_P();
61     Mx res,t;
62     t.clear();
63     res.stand();
64     //construct 枚举第i个字符为j
65     for(int i = 0; i < M; ++i){
66         for(int j = 0; j < 10; ++j){
67             int pos = i;
68             while(pos > 0 && s[pos + 1] - '0' != j) pos = P[pos];
69             if(s[pos + 1] - '0' == j) pos++;
70             t.a[pos][i] = (t.a[pos][i] + 1) % K;
71         }
72     }
73     //matrix pow
74     while(N){
75         if(N & 1) res = res * t;
76         t = t * t;
77         N >>= 1;
78     }
79     int ans = 0;
80     for(int i = 0; i < M; ++i) ans = (ans + res.a[i][0]) % K;
81     printf("%d\n",ans);
82     return 0;
83 }
84     
85     

 

posted @ 2014-12-15 22:31  Naturain  阅读(135)  评论(0编辑  收藏  举报