• bzoj 3676: [Apio2014]回文串【后缀自动机+manacher】


    用manacher找出本质不同的回文子串放在SAM上跑

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    using namespace std;
    const int N=600005;
    int n,p[N];
    char s[N],c[N];
    long long ans;
    struct SAM	
    {
    	int la,cnt,pos[N],len[N],si[N],sa[N],fa[N],ch[N][27],c[N],f[N][19],de[N];
    	SAM()
    	{
    		la=++cnt;
    	}
    	void ins(int c,int id)
    	{
    		int p=la,cur=la=++cnt;
    		len[cur]=len[p]+1;
    		si[cur]=1;
    		pos[id]=la;
    		for(;p&&!ch[p][c];p=fa[p])
    			ch[p][c]=cur;
    		if(!p)
    			fa[cur]=1;
    		else
    		{
    			int q=ch[p][c];
    			if(len[q]==len[p]+1)
    				fa[cur]=q;
    			else
    			{
    				int nt=++cnt;
    				len[nt]=len[p]+1;
    				memcpy(ch[nt],ch[q],sizeof(ch[q]));
    				fa[nt]=fa[q];
    				fa[q]=fa[cur]=nt;
    				for(;ch[p][c]==q;p=fa[p])
    					ch[p][c]=nt;
    			}
    		}
    	}
    	void wk()
    	{
    		for(int i=1;i<=cnt;i++)
    			c[len[i]]++;
    		for(int i=1;i<=n;i++)
    			c[i]+=c[i-1];
    		for(int i=cnt;i>=1;i--)
    			sa[c[len[i]]--]=i;
    		for(int i=cnt;i>=1;i--)
    			si[fa[sa[i]]]+=si[sa[i]];
    		for(int i=1;i<=cnt;i++)
    		{
    			int u=sa[i];
    			de[u]=de[fa[u]]+1;
    			f[u][0]=fa[u];
    			for(int j=1;(1<<j)<=de[u];j++)
    				f[u][j]=f[f[u][j-1]][j-1];
    		}
    	}
    	void ques(int l,int r)
    	{
    		int x=pos[r];
    		for(int i=18;i>=0;i--)
    			if(len[f[x][i]]>=r-l+1)
    				x=f[x][i];
    		ans=max(ans,1ll*si[x]*(r-l+1));//cerr<<l<<" "<<r<<" "<<si[x]*(r-l+1)<<endl;
    	}
    }sam;
    int main()
    {
    	scanf("%s",s+1);
    	n=strlen(s+1);
    	for(int i=1;i<=n;i++)
    		sam.ins(s[i]-'a',i);
    	sam.wk();
    	s[0]='+';s[n+1]='*';
    	int mx=0,id;
    	for(int i=1;i<=n;i++)
    	{
    		if(mx>i)
    			p[i]=min(mx-i,p[2*id-i-1]);
    		else 
    			p[i]=0;
    		while(s[i+p[i]+1]==s[i-p[i]])
    		{
    			p[i]++;
    			sam.ques(i-p[i]+1,i+p[i]);
    		}
    		if(p[i]+i>mx)
    			mx=p[i]+i,id=i;
    	}
    	mx=0;
    	for(int i=1;i<=n;i++)
    	{
    		if(mx>i)
    			p[i]=min(mx-i-1,p[2*id-i]);
    		else 
    		{
    			p[i]=1;
    			sam.ques(i-p[i]+1,i+p[i]-1);
    		}
    		while(s[i+p[i]]==s[i-p[i]])
    		{
    			p[i]++;
    			sam.ques(i-p[i]+1,i+p[i]-1);
    		}
    		if(p[i]+i>mx)
    			mx=p[i]+i,id=i;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    初心,勇敢~
    京东云,100倍故障时长赔付,呵呵
    京东万象数据接口,钱没花完,接口404,客服是白痴,无法维权
    随便写点
    关于UltraEdit的两个小问题
    Java
    2016年12月12日 回忆录随笔----------记录庸碌无为的一年四个月零十一天(一)
    iOS开发学习笔记
    sprintf函数php的详细使用方法
    BMS开发日记
  • 原文地址:https://www.cnblogs.com/lokiii/p/8891486.html
Copyright © 2020-2023  润新知