BZOJ 3676 Apio2014 回文串 回文自动机

题目大意:定义一个回文串的出现值为出现次数*长度,求最大出现值

我并不知道这道题曾经的解法是什么,但是自从回文自动机出现之后它成为了一道裸题。。。裸题。。。裸题。。。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 300300
using namespace std;
int n;
long long ans;
char s[M<<1];
namespace Palindrome_Automaton{
	struct Trie{
		Trie *son[27],*fail;
		int dpt,cnt;
		Trie() {}
		Trie(int _):dpt(_) {}
	}mempool[M<<1],*C=mempool;
	Trie *root=new (C++)Trie(0),*last=root;
	void Extend(int x)
	{
		Trie *p=last;
		while(s[x-2*p->dpt]!=s[x])
			p=p->fail;
		if(p->son[s[x]-'`'])
			last=p->son[s[x]-'`'];
		else
		{
			last=p->son[s[x]-'`']=new (C++)Trie(p->dpt+1);
			for(p=p->fail;p;p=p->fail)
				if(s[x-2*p->dpt]==s[x])
				{
					last->fail=p->son[s[x]-'`'];
					break;
				}
			if(!p) last->fail=root;
		}
		last->cnt++;
	}
}
void BFS()
{
	using namespace Palindrome_Automaton;
	static Trie *q[M<<1];
	int i,r=0,h=0;
	q[++r]=root;
	while(r!=h)
	{
		Trie *p=q[++h];
		for(i=0;i<=26;i++)
			if(p->son[i])
				q[++r]=p->son[i];
	}
	for(i=r;i>1;i--)
	{
		Trie *p=q[i];
		p->fail->cnt+=p->cnt;
		ans=max(ans,(long long)(p->dpt-1)*p->cnt);
	}
}
int main()
{
	using namespace Palindrome_Automaton;
	int i;
	scanf("%s",s+1);n=strlen(s+1);
	for(i=n<<1|1;i;i--)
	{
		if(i&1)
			s[i]='`';
		else
			s[i]=s[i>>1];
	}
	for(i=1;i<=(n<<1|1);i++)
		Extend(i);
	BFS();
	cout<<ans<<endl;
	return 0;
}


你可能感兴趣的:(bzoj,回文自动机,BZOJ3676)