KMP之Count the string

B - Count the string

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

汉化:

众所周知,AekdyCoin善于处理字符串问题以及数论问题。当给定一个字符串s时,我们可以写下这个字符串的所有非空前缀。例如:
s:“abab”
前缀是:“a”,“ab”,“aba”,“abab”
对于每个前缀,我们可以计算它在s中匹配的时间。所以我们可以看到前缀“a”匹配两次,“ab”匹配两次,“aba”匹配一次,“abab”匹配一次。现在要求您计算所有前缀的匹配时间总和。对于“abab”,是2 + 2 + 1 + 1 = 6。
答案可能非常大,所以输出答案mod 10007。
输入
第一行是一个整数T,表示测试用例的数量。
对于每种情况,第一行是一个整数n(1 <= n <= 200000),它是字符串s的长度。在给出字符串s之后的一行。字符串中的字符全部是小写字母。
产量
对于每种情况,只输出一个数字:s mod 10007的所有前缀的匹配时间总和。
示例输入
1
4
ABAB
示例输出
6

当初我在做C题的时候有人跟我说这道题特别简单让我先看看这道。题目很简单,直接看示例输入和示例输出就能明白。我的第一个感觉就是这道题和A题很像。把A题改一改就可以把这道题解出来。然而这么做了以后TLE。。。

思路像是进入了一个误区,总想着建立一个新数组后把原数组的前一个、前两个……一直到前n个赋值进去。当然超时。然后就想通过memcpy复制的方法减少循环次数……后来就考虑找规律,还是同一个人跟我说,新数组f取值取到原数组s的一半的时候后面的值都是1。信他才有鬼。(举个栗子,asasas不就是3+3+2+2+1+1.)

当然不断地卡时间,卡得我怀疑人生。其实这时候我已经发现原方法行不通。缺一个打通任督二脉的契机。晚上队里的大佬临走之前指点了一句“你想想next是干啥的”

后来,还是那个人,他在网上搜到了其他大佬的做法,还给我发了链接:

http://blog.csdn.net/zsgg_acm/article/details/39642145 PS:这位大佬写得非常简短,慎点。

所以我当然没用这个方法啦。

直到我扒了他的一篇博客。地址:http://blog.csdn.net/CrazyForsaken/article/details/79110830

这才明白他是啥意思==具体代码如下:

#include "cstdio"
#include "algorithm"
#include "cstring"
#include "iostream"
#include "string.h"
using namespace std;

int ne[200005];
char s[200010];

void GetNext(int len)
{
     int i = 0, j = -1;
     ne[0] = -1;
     while(i < len)
     {
          if(j == -1 || s[i] == s[j])
          {
               ne[++i] = ++j;
          }
          else j = ne[j];
    }
}
///GetNext函数基本上没动。
int main()
{
     int t, n;
     scanf("%d", &t);
     while(t--)
     {
          char f[200005];
          scanf("%d, s", &n, s);
          GetNext(n);
          memset(f,, sizeof(f));
          int ans = 0;
          for(int i = 1; i <= n; i++)
          {
               int cnt = ne[i];
               f[i] = (f[cnt] + 1);
               ans = (ans + f[i]) % 10007;
          }
          printf("%d\n", ans);
     }
     return 0;
}

另外,卡时间都是因为太暴力了。

题还没做完,等做完了再写总结吧。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值