【uoj5】 NOI2014—动物园

http://uoj.ac/problem/5 (题目链接)

题意

  求字符串各个前缀的前缀与后缀相同但不重叠的子串的个数+1之积

Solution

  KMP。第一遍求next和符合条件的可以重叠的子串。第二遍,求符合条件的不重叠的子串,注意此时不可以重新求next,直接使用上次求出来的next。

代码

// uoj5
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf (1ll<<30)
#define MOD 1000000007
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;

const int maxn=1000010;
int next[maxn],num[maxn],sum[maxn];
char s[maxn];

int main() {
	int T;scanf("%d",&T);
	while (T--) {
		scanf("%s",s+1);
		int n=strlen(s+1);
		next[1]=0;sum[0]=-1;num[0]=-1;
		for (int j=0,i=2;i<=n;i++) {
			while (j && s[j+1]!=s[i]) j=next[j];
			if (s[j+1]==s[i]) j++;
			next[i]=j;sum[i]=sum[j]+1;
		}
		for (int j=0,i=2;i<=n;i++) {
			while (j && (s[j+1]!=s[i] || j+1>i/2)) j=next[j];
			if (s[j+1]==s[i]) j++;
			num[i]=sum[j]+1;
		}
		LL ans=1;
		for (int i=1;i<=n;i++) ans=ans*(num[i]+1)%MOD;
		printf("%lld\n",ans);
	}
	return 0;
}

 

posted @ 2017-02-10 11:31  MashiroSky  阅读(...)  评论(...编辑  收藏