BZOJ 3676: [Apio2014]回文串

Description

考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最 
大出现值。 \(n\leqslant 10^5\)

Solution

回文自动机.

回文自动机的构造很简单..直接暴力找到第一个,然后暴力找到fail...

由于一个长度为n的字符串中本质不同的回文串个数是\(O(n)\)的,所以每个结点只会被fail访问一次,所以复杂度还是\(O(n)\)的..

https://pan.baidu.com/s/1o6BtDJs

Code

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N = 3e5+500;
const int M = 27;

struct PAM {
	int cnt,lst;
	int go[N][M],l[N],f[N],sz[N];
	char s[N];
	
	void init() { scanf("%s",s+1),l[1]=-1,f[0]=1,cnt=1; }
	void Add(int x,int n) {
		int p=lst;
		while(s[n-l[p]-1]!=s[n]) p=f[p];
		if(!go[p][x]) {
			int np=++cnt,k=f[p];l[np]=l[p]+2;
			while(s[n]!=s[n-l[k]-1]) k=f[k];
			f[np]=go[k][x],go[p][x]=np;
		}sz[lst=go[p][x]]++;
	}
	LL get_ans() {
		int n=strlen(s+1);
		for(int i=1;i<=n;i++) Add(s[i]-'a'+1,i);
		LL res=0;
		for(int i=cnt;~i;--i) sz[f[i]]+=sz[i],res=max(res,(LL)l[i]*sz[i]);
		return res;
	}
}py;

int main() {
	py.init();
	printf("%lld\n",py.get_ans());
	return 0;
}

  

posted @ 2017-04-17 20:15  北北北北屿  阅读(137)  评论(0编辑  收藏  举报