【KMP】[Noi2014] bzoj3670 动物园

题目点这里

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

感觉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;
}
    原文作者:KMP算法
    原文地址: https://blog.csdn.net/qq_21841245/article/details/44491867
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞