【KMP】[Noi2014] bzoj3670 动物园

来源:互联网 发布:海康矩阵 编辑:程序博客网 时间:2024/04/30 09:22

题目点这里


记得第一次看这道题。。林伟平在讲课。。。然后我看到那句企鹅只会卖萌要吃的。。就笑了出来。。。于是……

感觉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;}


1 0
原创粉丝点击