HDU 3336 Count the string(next数组应用)

题意:

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

1
4
abab

Sample Output

6

思路:一开始对着有循环节的字符串在那推,结果WA了三发,,然后重新开始找错误样例,,重新想才想明白,先求next数组,从后面的前缀往前推,next指的位置就是当前 前缀的前后缀相同的最大长度,

画图理解一下,

那么这个前缀的前缀出现的次数还要加上前缀出现的次数,即每次出现这个前缀时,前缀的前缀后缀相同的位置,相当于这个前缀的前缀出现了两次,不过因为是从后往前推,前面长的前缀求的时候已经加上一次了。

对着字符串拼拼看看,并不难理解。

代码:

#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
#define mod 10007
#define maxn 300005
void getnext(char *ch,int *next)
{
    int x=strlen(ch);
    next[0]=0;
    for(int i=1,p=0;i0&&ch[i]!=ch[p])
        {
            p=next[p-1];
        }
        if(ch[p]==ch[i]) p++;
        next[i]=p;
    }
}
int kmp(char *ch,char *chh,int *next)///查询ch内含有chh字串个数
{
    int n=strlen(ch),m=strlen(chh),j=0,i=0,ans=0;
    while(i=0;i--)
        {
            ans[i]+=1;
            ans[i]%=mod;
            anss+=ans[i];//cout<=0)
            ans[nex[i]-1]+=ans[i];
        }

        printf("%lld\n",anss);
    }
}

 

你可能感兴趣的:(数据结构)