您的位置:首页 > 其它

[BZOJ]3676: [Apio2014]回文串 回文自动机

2017-09-18 14:54 316 查看
Description

考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出

现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最

大出现值。

题解:

回文自动机入门,存模板,骗访问量。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=300010;
char str[maxn];
struct pam{int len,fail,son[28],num,cnt;}tr[maxn];
int n,last,z;
void pre()
{
n=last=0;z=1;
tr[0].len=0;tr[1].len=-1;
tr[0].fail=1;
}
int L;
int get_fail(int x)
{
while(str
!=str[n-tr[x].len-1])x=tr[x].fail;
return x;
}
void add(int x)
{
n++;
int p=get_fail(last);
if(!tr[p].son[x])
{
z++;
tr[z].len=tr[p].len+2;
tr[z].fail=tr[get_fail(tr[p].fail)].son[x];
tr[p].son[x]=z;
tr[z].num=tr[tr[z].fail].num+1;
}
last=tr[p].son[x];
tr[last].cnt++;
}
LL ans=0;
void solve()
{
for(int i=z;i;i--)tr[tr[i].fail].cnt+=tr[i].cnt;
for(int i=0;i<=z;i++)ans=max(ans,(LL)(tr[i].len)*(LL)(tr[i].cnt));
}
int main()
{
scanf("%s",str+1);
str[0]='#';
L=strlen(str+1);
pre();
for(int i=1;i<=L;i++)add(str[i]-'a');
solve();
printf("%lld",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: