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;
}
原文地址:https://www.cnblogs.com/lokiii/p/8891486.html