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.

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]]结尾的前缀。


View Code
 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步骤差不多,就是这个字符和首个字符往后走,遇到不
一样又重复这个步骤。。。
 
代码如下:
View Code
 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 }

 

相关文章:

  • 2022-12-23
  • 2021-06-17
  • 2022-12-23
  • 2021-09-17
  • 2022-03-03
  • 2021-11-18
  • 2021-10-21
  • 2022-12-23
猜你喜欢
  • 2021-09-23
  • 2022-12-23
  • 2021-10-03
相关资源
相似解决方案