zoukankan      html  css  js  c++  java
  • CF 235C. Cyclical Quest(后缀自动机)

    传送门

    解题思路

      字符串(a)(b)中出现次数,一定后缀自动机了。对文本串(s)建一个后缀自动机,预处理出倍增数组和(right)集合。考虑统计答案,对于每个模式串,因为要求出所有同构,那么就先倍长这个串,然后扫的过程中要维护在后缀自动机上匹配了多少位(tmp),当(tmp>=len)时说明可以做出贡献,那么就找到一个现在节点的最高祖先满足(l_x>=len),然后把此处的(right)集合大小加入答案。但是这样会算重复,就要给计算过答案的每个状态打个标记,撤销时用栈。数组开小调了半天。,

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    
    using namespace std;
    const int N=2000005;
    typedef long long LL;
    
    int n,len,a[N],c[N],stk[N],top,f[N][22];
    LL ans;
    char s[N],t[N];
    bool vis[N];
    
    struct SAM{
    	int fa[N],ch[N][28],l[N],siz[N],cnt,lst;
    	void Insert(int c){
    		int p=lst,np=++cnt; l[np]=l[p]+1; lst=cnt; siz[np]=1;
    		for(;p && !ch[p][c];p=fa[p]) ch[p][c]=np;
    		if(!p) fa[np]=1;
    		else {
    			int q=ch[p][c];
    			if(l[q]==l[p]+1) fa[np]=q;
    			else {
    				int nq=++cnt; l[nq]=l[p]+1;
    				memcpy(ch[nq],ch[q],sizeof(ch[nq]));
    				fa[nq]=fa[q]; fa[q]=fa[np]=nq;
    				for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
    			}
    		}
    	}
    	void solve(){
    		for(int i=1;i<=cnt;i++) c[l[i]]++;
    		for(int i=1;i<=cnt;i++) c[i]+=c[i-1];
    		for(int i=1;i<=cnt;i++) a[c[l[i]]--]=i;
    		for(int i=cnt;i;i--) siz[fa[a[i]]]+=siz[a[i]];
    		for(int i=2;i<=cnt;i++){
    			int p=a[i]; f[p][0]=fa[p];
    			for(int j=1;j<=20;j++)
    				f[p][j]=f[f[p][j-1]][j-1];
    		}
    	}
    }sam;
    
    int main(){
    	scanf("%s%d",s+1,&n); sam.cnt=sam.lst=1; len=strlen(s+1);
    	for(int i=1;i<=len;i++) sam.Insert(s[i]-'a'+1);
    	sam.solve(); int now,tmp;
    	for(int i=1;i<=n;i++){
    		scanf("%s",t+1); len=strlen(t+1);
    		for(int j=1;j<=len;j++) t[j+len]=t[j];
    		now=1; ans=0; tmp=0; top=0;
    		for(int j=1;j<=len*2;j++){
    			if(sam.ch[now][t[j]-'a'+1]) now=sam.ch[now][t[j]-'a'+1],tmp++;
    			else {	
    				for(;now && !sam.ch[now][t[j]-'a'+1];now=sam.fa[now]);
    				if(!now) now=1,tmp=0;
    				else tmp=sam.l[now]+1,now=sam.ch[now][t[j]-'a'+1];
    			}
    			if(tmp>=len) {
    				int zz=now;
    				for(int k=20;k>=0;k--)
    					if(f[zz][k] && sam.l[f[zz][k]]>=len) zz=f[zz][k];
    				if(vis[zz]) continue; vis[zz]=1; stk[++top]=zz;
    				ans+=sam.siz[zz];
    			}
    		}
    		while(top) vis[stk[top--]]=0;
    		printf("%lld
    ",ans); 
    	}
    	return 0;
    }	
    
  • 相关阅读:
    多条件搜索问题 -sql拼接与参数化查询
    MVC View中获取action、controller、area名称、参数
    Hadoop权限认证的执行流程
    Java API操作HA方式下的Hadoop
    利用HBase的快照功能来修改表名
    hive两大表关联优化试验
    Spark SQL与Hive on Spark的比较
    Spark的RDD原理以及2.0特性的介绍
    hbase Java API 介绍及使用示例
    初识Spark2.0之Spark SQL
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/10454989.html
Copyright © 2011-2022 走看看