KMP---Count the string

题目网址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110060#problem/A

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.
adfsa

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

1
4
abab 

Sample Output

6 

题意: 给一个字符串,求这个字符串的所有前缀在字符串中出现的次数和。

思路: 使用next[]跳转表,已经有了next数组,next[i]=k表示最大的j使得0~k-1==i-k+1~i,因此,对于样例abab,则有

       0   1   2   3

s[]  a    b   a   b

p[]  0    0   1   2

对于4个前缀:

a

ab

aba

abab

设dp[i]表示子串s[0~i]共含有以s[i]为结尾的前缀的数目,则以s[i]结尾的前缀数就是自己本身加上以s[p[i]]结尾的前缀数,也就是例如i=2

则有:p[i]=1,dp[i]=dp[p[i]-1]+1 ;

a

aba这两个前缀,其中a就是s[p[i]]结尾的前缀。

本题代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
char s[200005];
int  p[200005];
int  dp[200005];
int n;

int next_()
{
    int k=0;
    int sum=1;
    int len=strlen(s);
    p[0]=0;
    dp[0]=1;
    for(int i=1;i<len;i++)
    {
        while(k>0&&s[k]!=s[i])
            k=p[k-1];
        if(s[k]==s[i])
            k++;
        if(k>0) dp[i]=(dp[k-1]+1)%10007;
        else    dp[i]=1;
        sum=(sum+dp[i])%10007;
        p[i]=k;
    }
    return sum;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%s",&n,s);
        printf("%d
",next_());
    }
    return 0;
}
原文地址:https://www.cnblogs.com/chen9510/p/5308134.html