http://blog.csdn.net/yearn520/article/details/6729426
http://www.cnblogs.com/c-cloud/p/3224788.html
前辈写的详解请参考;
对于一个字符串,我们可以写出这个字符串的所有非空前缀。例如“abab”,非空前缀有:“a”,“ab”,“aba”,“abab”。对于每一个前缀,我们可以计算出他在原字符串中出现的次数。所以我们可以看到,“a”在原字符串中出现了2次;
“ab”在原字符串中出现了2次;“aba”出现了1次;“abab”出现了一次。
现在,要求您计算出给定的字符串的所有非空前缀出现的次数之和。对于“abab”,答案就是2+2+1+1=6。
由于答案可能非常大,所以要求输出答案对10007取模的值。
Input
输入由2行组成;
第一行输入一个正整数n(n<=1000000),代表字符串的长度;
第二行输入一个长度为n的字符串,只由小写字母构成。
Output
输出由一行组成;
输出一个整数,代表给定的字符串的所有非空前缀出现的次数之和对10007取模的值。
Sample Input
4
abab
Sample Output
6
Hint
#include<stdio.h>
#include<string.h>
int n;
char b[1000006]={0};
int next[1000006]={0};//记录前缀b[1]-b[i]中包含了前缀b[1]-b[j]中的j值;(并不包括自身和b[1]-b[i-1])
int dp[1000006]={0};//记录每个前缀的总个数;
void sourch()
{
int i;
int j=0;//表示前缀是b[1]-b[j]中的j;
for(i=2;i<=n;i++)
{
while(j>0&&b[j+1]!=b[i])//前缀b[1]-b[i]是否包含了前缀b[1]-b[j+1]
j=next[j];//前缀b[1]-b[i]不包含前缀b[1]-b[j+1]所以要缩小到前缀的b[1]-b[next[j]]查看是否包含;
if(b[j+1]==b[i])//如果此时前缀b[1]-b[i]是否包含了前缀b[1]-b[j+1]
j+=1;//
next[i]=j;
}
}
int main()
{
int i;
int sum=0;
scanf("%d",&n);
scanf("%s",b+1);
sourch();
for(i=1;i<=n;i++)
{
dp[i]=dp[next[i]]+1;(加上自身)
sum=(sum+dp[i])%10007;
}
printf("%d\n",sum);
}