题目描述
给你一个由小写拉丁字母组成的字符串 ss 。我们定义 ss 的一个子串的存在值为这个子串在 ss 中出现的次数乘以这个子串的长度。
对于给你的这个字符串 ss ,求所有回文子串中的最大存在值。
输入输出格式
输入格式:
一行,一个由小写拉丁字母(a~z)组成的非空字符串 ss 。
输出格式:
输出一个整数,表示所有回文子串中的最大存在值。
输入输出样例
输入样例#1:
abacaba
输出样例#1:
7
输入样例#2:
www
输出样例#2:
4
题解
回文自动机的发明,给了我们极大的遍历,我们只需要建出回文自动机,遍历一遍所有的节点,每一个节点代表一个字符串
长度为
len[i]
l
e
n
[
i
]
,出现次数为
cnt[i]
c
n
t
[
i
]
,直接乘起来就可以.
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#define ll long long
#define N 26
const int MAXN=1e6;
using namespace std;
char s[MAXN];
struct Palindromic_Tree
{
int Next[MAXN][26],num[MAXN],fail[MAXN],cnt[MAXN],len[MAXN],S[MAXN];
int last,n,p;
int newNode(int l)
{
for(int i=0;i<N;i++) Next[p][i]=0;
cnt[p]=0;num[p]=0;len[p]=l;
return p++;
}
void Init()
{
p=0;
newNode(0);newNode(-1);
last=0;n=0;
S[n]=-1;fail[0]=1;
}
int Get_Fail(int x)
{
while(S[n-len[x]-1]!=S[n])
x=fail[x];
return x;
}
void Add(int c)
{
c-='a';
S[++n]=c;
int cur=Get_Fail(last);
if(!Next[cur][c])
{
int now=newNode(len[cur]+2);
fail[now]=Next[Get_Fail(fail[cur])][c];
Next[cur][c]=now;
num[now]=num[fail[now]]+1;
}
last=Next[cur][c];
cnt[last]++;
}
void Count()
{
for(int i=p-1;i>=0;i--)
cnt[fail[i]]+=cnt[i];
}
}Tmotfl;
int main()
{
Tmotfl.Init();
scanf("%s",s);
int len=strlen(s);
for(int i=0;i<len;i++)
{
Tmotfl.Add(s[i]);
}
Tmotfl.Count();
ll Max=-1;
for(int i=1;i<=Tmotfl.p;i++)
{
Max=max(Max,1ll*Tmotfl.cnt[i]*Tmotfl.len[i]);
}
printf("%lld",1ll*Max);
return 0;
}