[APIO2014] 回文串

题面在这里!

    新学了一种神奇的数据结构叫回文树,然后就神奇的不用学马拉车了哈哈哈哈(之前还老被嘲讽不会马拉车QWQ)

    非常nice的一点是,学完回文树之后发现它和AC自动机的原理几乎是一模一样的!所以只要会懂了AC自动机的原理回文树分分钟学会的事啊QWQ

    回文树里的fail边代表某个回文子串的最长回文后缀子串节点是什么,然后ch[]就是在回文串的两端都加上同一个字母会转移到哪个节点。。。

    本质相同的回文串就是回文树里的一个节点,所以就可以很方便的处理出现次数和长度等最大值或者计数问题了hhhh

    (建议看一下某年讲这个的集训队论文)

    

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=310005;

int len[maxn],sum[maxn],ch[maxn][26];
int n,c,cnt,now,fl[maxn],p;
char s[maxn];
ll ans=0;

int main(){
	scanf("%s",s+1),n=strlen(s+1),s[0]='?';
	
	len[1]=-1,fl[0]=1,now=cnt=1;
	
	for(int i=1;i<=n;now=ch[now][c],sum[now]++,i++){
        c=s[i]-'a';
        
		for(;s[i-len[now]-1]!=s[i];now=fl[now]);
		
		if(!ch[now][c]){
			ch[now][c]=++cnt;
			len[cnt]=len[now]+2;
			
			if(len[cnt]==1) continue;
			
			p=fl[now];
			for(;s[i-len[p]-1]!=s[i];p=fl[p]);
			fl[cnt]=ch[p][c];
		}
	}
	
	for(int i=cnt;i>=2;i--){
		sum[fl[i]]+=sum[i];
		ans=max(ans,len[i]*(ll)sum[i]);
	}
	
	printf("%lld\n",ans);
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/JYYHH/p/9213534.html