zoukankan      html  css  js  c++  java
  • Codeforces 235C Cyclical Quest 字符串 SAM KMP

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF235C.html

    题目传送门 -  CF235C

    题意

      给定一个字符串 $s$ ,多组询问,每组询问的形式为一个字符串 $T$ ,问 $S$ 有多少个子串与 $T$ 循环同构。(如果 $S$ 有多个相同子串都同构,则算多次)

      $|S|leq 10^6,sum |T|leq 10^6$

    题解

      给 $S$ 建一个 SAM ,然后对于每一个 $T$ KMP 一下,找到最大循环节,在 SAM 上面走一走就可以了。

    代码

    #include <bits/stdc++.h>
    #define right _47hurnf
    using namespace std;
    typedef long long LL;
    const int N=1000005;
    int n,m;
    char s[N];
    struct SAM{
    	int Next[26],fa,Max;
    }t[N<<1];
    int tax[N],id[N<<1],right[N<<1];
    int size;
    void init(){
    	memset(t,0,sizeof t);
    	size=1,t[0].Max=-1;
    	for (int i=0;i<26;i++)
    		t[0].Next[i]=1;
    }
    int extend(int p,int c){
    	if (t[p].Next[c]&&t[p].Max+1==t[t[p].Next[c]].Max)
    		return t[p].Next[c];
    	int np=++size,q,nq;
    	t[np].Max=t[p].Max+1;
    	for (;!t[p].Next[c];p=t[p].fa)
    		t[p].Next[c]=np;
    	q=t[p].Next[c];
    	if (t[p].Max+1==t[q].Max)
    		t[np].fa=q;
    	else {
    		nq=++size;
    		t[nq]=t[q],t[nq].Max=t[p].Max+1;
    		t[q].fa=t[np].fa=nq;
    		for (;t[p].Next[c]==q;p=t[p].fa)
    			t[p].Next[c]=nq;
    	}
    	return np;
    }
    int Fail[N];
    int KMP(char s[],int n){
    	Fail[0]=Fail[1]=0;
    	for (int i=2;i<=n;i++){
    		int k=Fail[i-1];
    		while (k>0&&s[i]!=s[k+1])
    			k=Fail[k];
    		Fail[i]=k+(s[k+1]==s[i]?1:0);
    	}
    	int x=Fail[n];
    	while (x>0&&n%(n-x)!=0)
    		x=Fail[x];
    	return n-x;
    }
    int main(){
    	scanf("%s",s+1);
    	n=strlen(s+1);
    	init();
    	for (int i=1,p=1;i<=n;i++)
    		p=extend(p,s[i]-'a'),right[p]++;
    	for (int i=1;i<=size;i++)
    		tax[t[i].Max]++;
    	for (int i=1;i<=n;i++)
    		tax[i]+=tax[i-1];
    	for (int i=1;i<=size;i++)
    		id[tax[t[i].Max]--]=i;
    	for (int i=size;i>=1;i--)
    		right[t[id[i]].fa]+=right[id[i]];
    	scanf("%d",&m);
    	while (m--){
    		scanf("%s",s+1);
    		int len=strlen(s+1),r=KMP(s,len);
    		LL ans=0;
    		int p=1,Matched=0;
    		for (int i=1;i<=len;i++){
    			int c=s[i]-'a';
    			while (!t[p].Next[c])
    				p=t[p].fa,Matched=t[p].Max;
    			p=t[p].Next[c];
    			Matched++;
    		}
    		for (int i=1;i<=r;i++){
    			int c=s[i]-'a';
    			while (!t[p].Next[c])
    				p=t[p].fa,Matched=t[p].Max;
    			p=t[p].Next[c];
    			Matched++;
    			while (t[t[p].fa].Max>=len)
    				p=t[p].fa,Matched=t[p].Max;
    			if (Matched>=len)
    				ans+=right[p];
    		}
    		printf("%I64d
    ",ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Lombok介绍、使用方法和总结
    JSONObject.fromObject
    idea多级目录不展开的问题
    SpringBoot | 查看默认版本配置
    常见的版本号及Springcloud的版本
    Spring Boot,Spring Security实现OAuth2 + JWT认证
    OAuth2实现原理
    什么是OAuth2
    springboot 实时监控 spring-boot-starter-actuator 包
    解决springboot 新版本 2.1.6 spring-boot-starter-actuator 访问报404
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/CF235C.html
Copyright © 2011-2022 走看看