Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 5 Accepted Submission(s) : 3
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
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.
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
看了喵呜的解题报告才知道这么做的:
这题是KMP的变形题,主要是了解next数组的用法。
题意是,给一串字符串,问这串字符串所有的前缀总共在这个字符串中出现了几次。
已经有了next数组,next[i]=j表示最大的j使得0~j==i-j~i,因此,对于样例abab,则有
0 1 2 3
b[] a b a b
p[] -1 -1 0 1
对于4个前缀:
a
ab
aba
abab
设dp[i]表示子串b[0~i]共含有以b[i]为结尾的前缀的数目,则以b[i]结尾的前缀数就是自己本身加上以b[p[i]]结尾的前缀数,也就是例如i=2
则有:
a
aba这两个前缀,其中a就是b[p[i]]结尾的前缀。
1 #include <iostream> 2 #include <stdio.h> 3 using namespace std; 4 5 int dp[200005]; 6 char b[200005]; 7 int p[200005]; 8 int n; 9 10 int find() 11 { 12 int ans=1; 13 int i,j; 14 dp[0]=1; 15 j=-1; 16 p[0]=-1; 17 for(i=1;i<n;i++) 18 { 19 while(j>=0 && b[j+1]!=b[i]) j=p[j]; 20 if(b[j+1]==b[i]) j++; 21 if(j>=0) dp[i]=(dp[j]+1)%10007; // 出去这两行就是原来简单的KMP 就pre数组。 22 else dp[i]=1; // 23 p[i]=j; 24 ans=(ans+dp[i])%10007; 25 } 26 return ans; 27 } 28 29 int main() 30 { 31 int i,j,t; 32 scanf("%d",&t); 33 while(t--) 34 { 35 scanf("%d",&n); 36 scanf("%s",b); 37 printf("%d\n",find()); 38 } 39 //system("pause"); 40 return 0; 41 }
对于这一题还有个比较耗时间的做法:
1、首先确定下这个字符串的首个字母,然后从第二个开始搜起
当遇到和首字符一样的时候,就从该字母开始和这个字符串的首
个字符开始进行比较,知道出现不一样为止,此时相同的个数就
加到总数上。
2、不一样的话就从和首个字符一样的位置的下一个字符开始。
然后和1步骤差不多,就是这个字符和首个字符往后走,遇到不
一样又重复这个步骤。。。
代码如下:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 using namespace std; 5 6 char str[200005]; 7 8 int main() 9 { 10 int i,j,n,sum; 11 int t; 12 scanf("%d",&t); 13 while(t--) 14 { 15 scanf("%d",&n); 16 sum=n; 17 sum=sum%10007; 18 scanf("%s",str); 19 for(i=1;i<n;i++) 20 { 21 if(str[i]==str[0]) 22 { 23 for(j=i;j<n;j++) 24 { 25 if(str[j]!=str[j-i]) 26 break; 27 } 28 29 sum+=j-i; 30 sum=sum%10007; 31 } 32 } 33 printf("%d\n",sum); 34 } 35 return 0; 36 }