记得第一次看这道题。。林伟平在讲课。。。然后我看到那句企鹅只会卖萌要吃的。。就笑了出来。。。于是……
感觉noi2014的题很考语文水平啊。。之前day1前两题我题全都看错orz。。第三题根本不造在做啥。。。。这道题我研究了很久才知道它是要求什么。。。
对于每个 0 < i < strlen(s) 定义一个 num[i] 表示 s[1…k] == s[j…i] (其中 1 <= k < j <= i) 的个数
然后。。。题目都告诉是KMP了 所以这题就是KMP乱搞了……
KMP是一个fix指针指向失配的位置。。那么这道题用两个指针就好了。。。。
一个指针和KMP的是一样的 另一个指向合法的失配点 也就是说 fix * 2 <= i
然后可以发现 新的这个指针和第一个指针具有相同的性质。。就是说这一次的可以直接用上一次的信息。。。(越来越感觉自己语死早了)
所以就是第一个指针维护next数组 第二个维护num就行了。。 = =
然后这个num还得转化一下 因为我们的next表示的是失配指向哪里 不能表示要失配多少次才能到1(其实这个次数就是num!)
那么就记录一个cnt数组表示失配多少次就行了。。。
当然t这个num数组是不用存的啊 直接加到ans里。。哦对了你造这题要开 long long 吧!
#include <cstdio>
#include <iostream>
using namespace std;
int read()
{
int sign = 1, n = 0; char c = getchar();
while(c < '0' || c > '9'){ if(c == '-') sign = -1; c = getchar(); }
while(c >= '0' && c <= '9') { n = n*10 + c-'0'; c = getchar(); }
return sign*n;
}
typedef long long LL;
const int Nmax = 1000005;
const LL mod = 1000000007;
int N;
char s[Nmax];
int next[Nmax], cnt[Nmax];
int fix1, fix2;
int main()
{
for(N = read(); N--; )
{
scanf("%s", s + 1);
cnt[1] = 1; fix1 = fix2 = 0; LL ans = 1ll;
for(int i = 2; s[i]; ++i)
{
while(fix1 && s[i] != s[fix1 + 1]) fix1 = next[fix1];
if(s[i] == s[fix1 + 1]) ++fix1;
next[i] = fix1; cnt[i] = cnt[fix1] + 1;
while(fix2 && s[i] != s[fix2 + 1]) fix2 = next[fix2];
if(s[i] == s[fix2 + 1]) ++fix2;
while(fix2 > (i >> 1)) fix2 = next[fix2];
ans *= cnt[fix2] + 1; ans %= mod;
}
printf("%lld\n", ans);
}
return 0;
}