CF235C Cyclical Quest

题目

CF235C Cyclical Quest

化简题意:多个环型匹配串在文本串出现次数

做法

我们把环型串备份展开在文本串匹配

\(parent.len≥len\)时我们要跳父亲,因为要找\(endpos\)

\(now.len≥len\)时我们就可以统计答案了,为保证时间复杂度,我们不会把环型匹配串分成\(n\)个串匹配,所以\(now.len>len\)实际上大于的部分我们不需要管了,反正已经找到当前串状态的\(endpos\)直接加就好了

My complete code

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef int LL;
const LL maxn=3000009;
LL nod=1,lst=1,q;
LL len[maxn],fail[maxn],val[maxn],sum[maxn],a[maxn],son[maxn][26];
LL visit[maxn];
char s[maxn];
inline void Insert(LL c){
	LL np=++nod,p=lst; lst=np;
	len[np]=len[p]+1;
	while(p&&!son[p][c]){
		son[p][c]=np;
		p=fail[p];
	}
	if(!p)
	    fail[np]=1;
	else{
		LL q=son[p][c];
		if(len[q]==len[p]+1)
		    fail[np]=q;
		else{
			LL nq=++nod; len[nq]=len[p]+1;
			memcpy(son[nq],son[q],sizeof(son[q]));
			fail[nq]=fail[q];
			fail[np]=fail[q]=nq;
			while(p&&son[p][c]==q){
				son[p][c]=nq;
				p=fail[p];
			}
		}
	}++val[lst];
}
int main(){
	scanf(" %s",s+1);
	for(LL i=1,Len=strlen(s+1);i<=Len;++i){
		LL c(s[i]-'a');
		Insert(c);
	}
	for(LL i=1;i<=nod;++i)
	    ++sum[len[i]];
	for(LL i=1,Len=strlen(s+1);i<=Len;++i)
	    sum[i]+=sum[i-1];
	for(LL i=1;i<=nod;++i)
	    a[sum[len[i]]--]=i;
	for(LL i=nod;i>=2;--i)
	    val[fail[a[i]]]+=val[a[i]];
	//for(int i=1;i<=nod;++i)
	//    printf("%d(%d) ",a[i],val[a[i]]);printf("\n");
	memset(visit,-1,sizeof(visit));
	scanf("%lld",&q);
	while(q--){
		scanf(" %s",s+1);
		LL Len=strlen(s+1);
		for(LL i=1;i<Len;++i)
		    s[i+Len]=s[i];
		LL now(1),L=0;
		long long ret(0);
		for(LL i=1;i<2*Len;++i){
			LL c(s[i]-'a');
			while(now&&!son[now][c]){
				now=fail[now];
				L=len[now];
			}
			if(!now){
				now=1;
				L=0;
			}else{
				now=son[now][c];
				++L;
			}
			while(now&&len[fail[now]]>=Len){
				now=fail[now];
				L=len[now];
			}
			if(L>=Len&&visit[now]!=q){
				ret+=(long long)val[now];
				visit[now]=q;
			}
		}
		printf("%lld\n",ret);
	}
	return 0;
}
posted @ 2019-01-24 10:13  y2823774827y  阅读(183)  评论(0编辑  收藏  举报