HDOJ 3336 Count the string

来源:互联网 发布:共产主义社会 知乎 编辑:程序博客网 时间:2024/05/28 11:29

Count the string

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7477    Accepted Submission(s): 3461


Problem Description
It is well known that AekdyCoin is good at string problems as well as number theory problems. When given a string s, we can write down all the non-empty prefixes of this string. For example:
s: "abab"
The prefixes are: "a", "ab", "aba", "abab"
For each prefix, we can count the times it matches in s. So we can see that prefix "a" matches twice, "ab" matches twice too, "aba" matches once, and "abab" matches once. Now you are asked to calculate the sum of the match times for all the prefixes. For "abab", it is 2 + 2 + 1 + 1 = 6.
The answer may be very large, so output the answer mod 10007.
 

Input
The first line is a single integer T, indicating the number of test cases.
For each case, the first line is an integer n (1 <= n <= 200000), which is the length of string s. A line follows giving the string s. The characters in the strings are all lower-case letters.
 

Output
For each case, output only one number: the sum of the match times for all the prefixes of s mod 10007.
 

Sample Input
14abab
 

Sample Output
6
 

Author
foreverlin@HNU
 

Source
HDOJ Monthly Contest – 2010.03.06
 

题意:输出所有前缀出现的次数。

拿到这题的时候我是没有头绪的。当然,DP问题本来就是一个玄学,再加上这题还得用到KMP算法对字符串进行处理,很难想到用DP去求解(当然也可能是小编我太渣了),我们用dp[i]表示i前面所出现的前缀重复的次数,因为KMP算法中next数组的定义,next[i]就是在i前面前缀重复的上一个位置,这个说法可能不怎么好理解,这里小编再做一个详细的解释,就比如aabaabaabaab这个字符串,next[6] = 3,next[9] = 6,next[12] = 6,因为next数组表示的是前缀后缀最大匹配长度,所以如果i-next[i]就是前缀的长度,而next[i]的值就是在这个字符串中上一次重复到这个前缀的位置。说到这里可能有人要问小编,这有什么用呢?得到了这个我就可以写出一个状态转移方程了,dp[i] = dp[next[i]] + 1;DP问题从来都是玄学……想到了这里的话这道题就可以dp迭代一下子就完成了。


#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 200000+10;const int MOD = 10007;char str[maxn];int nex[maxn];int dp[maxn];int n;void getNext(){int i=0,j=-1;nex[0] = -1;while(i < n){if(j == -1 || str[i] == str[j])nex[++i] = ++j;else j = nex[j];}}int main(){int T;scanf("%d",&T);while(T--){scanf("%d",&n);scanf("%s",str);getNext();memset(dp,0,sizeof(dp));int sum = 0;for(int i=1; i<=n; i++){dp[i] = dp[nex[i]]+1;sum = (sum+dp[i]) % MOD;}printf("%d\n",sum);}return 0;}


0 0