BZOJ--3670(KMP,变形)

2014-12-16 02:18:06

思路:bzoj果然都是好题....poj刷了几道kmp感觉自己基本掌握了,直到刷bzoj才知道自己的理解是有多么弱!

  这题需要从kmp定义出发来思考,在kmp过程中同时维护一个cnt数组,cnt[i]用来计算从i出发,不断i=P[i],需要几步达到0(相当于返回0的距离)

  这个cnt[i]的含义其实就是前i个字符组成的串,能找到多少个前缀使得有后缀与之相等(思考!)

  那么由于题目中的不重叠的限制,我们只要利用j = P[j],使得有最大的j使得:j * 2 <= i,那么num[i]=cnt[j]+1,这个j是随着循环不断维护的,所以不用每次都从i找回去。

 1 /*************************************************************************
 2     > File Name: b3670.cpp
 3     > Author: Natureal
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Mon 15 Dec 2014 10:33:20 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 const int maxn = 1000010;
28 
29 int n,len;
30 int P[maxn],cnt[maxn];
31 char s[maxn];
32 ll ans;
33 
34 int main(){
35     scanf("%d",&n);
36     while(n--){
37         scanf("%s",s + 1);
38         ans = 0;
39         len = strlen(s + 1);
40         P[1] = 0;
41         int j = 0;
42         cnt[1] = 1;
43         for(int i = 2; i <= len; ++i){
44             while(j > 0 && s[j + 1] != s[i]) j = P[j];
45             if(s[j + 1] == s[i]) j++;
46             P[i] = j;
47             cnt[i] = cnt[j] + 1;
48         }
49         j = 0;
50         ans = 1;
51         for(int i = 2; i <= len; ++i){
52             while(j > 0 && s[j + 1] != s[i]) j = P[j];
53             if(s[j + 1] == s[i]) j++;
54             while((j << 1) > i) j = P[j];
55             ans *= cnt[j] + 1;
56             ans %= 1000000007;
57         }
58         printf("%lld\n",ans);
59     }
60     return 0;
61 }

 

posted @ 2014-12-16 02:25  Naturain  阅读(199)  评论(0编辑  收藏  举报