hdu 3336(kmp+dp)

摘自:http://www.cnblogs.com/wuyiqi/archive/2012/01/05/2313746.html
题意:求给定字符串含前缀的数量

abab

前缀为

a

ab

aba

abab

abab中共有六个子串是前缀a a ab ab aba abab

所以答案为6

利用kmp中的匹配原理可以完美的解决此题

a---------d-----

   -----a---------d

               i         j

如上所示,假设两串字符完全相等,next[j]=i,代表s[1...i]==sum[j-i+1....j],这一段其实就是前缀

i~j之间已经不可能有以j结尾的子串是前缀了,不然next【j】就不是 i 了

设dp【i】:以string[i]结尾的子串总共含前缀的数量

所以dp[j]=dp[i]+1,即以i结尾的子串中含前缀的数量加上前j个字符这一前缀

 1 /*
 2 * kmp+dp
 3 */
 4 #include <cstdio>
 5 #include <iostream>
 6 
 7 using namespace std;
 8 
 9 const int N = 200005;
10 
11 char pat[N];
12 int next[N], dp[N];
13 
14 void indexNext() {
15     int k = 0;
16     next[1] = 0;
17     for (int i=2; pat[i]; ++i) {
18         while (k && pat[k+1]!=pat[i]) k = next[k];
19         if (pat[k+1] == pat[i]) ++k;
20         next[i] = k;
21     }
22 }
23 
24 int solve(int len) {
25     int sum = 0;
26     indexNext();
27     for (int i=1; i<=len; ++i) dp[i] = 1;
28     dp[0] = 0;
29     for (int i=1; i<=len; ++i) {
30         dp[i] += dp[next[i]];
31         sum += dp[i];
32         sum %= 10007;
33     }
34     return sum;
35 }
36 
37 int main() {
38     int t;
39     scanf ("%d", &t);
40     pat[0] = '#';
41     while (t--) {
42         int n;
43         scanf ("%d%s", &n, pat+1);
44         printf ("%d\n", solve(n));
45     }
46     return 0;
47 }

 

posted on 2012-05-07 12:56  Try86  阅读(1006)  评论(0)    收藏  举报