• 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("
    ");
    	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
    ",ret);
    	}
    	return 0;
    }
    
  • 相关阅读:
    MVC知识点01
    MVC知识点02
    ADO.NET基础01
    WinForm,MVC知识点
    C#基础01
    28、对多次使用的RDD进行持久化或Checkpoint
    27、优化数据结构
    26、高性能序列化类库
    25、诊断内存的消耗
    24、Checkpoint原理剖析
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10312910.html
Copyright © 2020-2023  润新知