Description
考虑一个只包含小写拉丁字母的符串 s。我们定义 s的一个子串 t的“出现值”为 t在 s中的出现次数乘以t的长度。 请你求出s的所有 回文子串中的最大出现值。
Input
输入只有一行,为一个只包含小写字母 (a−z) 的非空字符串 s。
Output
输出 一个整数,为 所有 回文子串 的最大 出现 值。
Sample Input
输入1:
abacaba
输入2:
www
Sample Output
输出1:
7
输出2:
4
Hint
题解
听题时一脸懵逼,只见dalao什么fail指针连来连去的,目光呆滞的看着黑板(其实心里默默问候了出题人全家)
首先,这是一颗几乎是裸的回文树
!!但是!!
回文树是什么?又怎么去实现?
只好找呀,但基本上没几个看懂的
最后找到一个Victor Wonder dalao%%%
才勉强对着标看懂
具体,我也不怎么会说,自行看dalao写的pdf脑补
代码
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;
int next[300005][30],fail[300005],len[300005],bz[300005],last,n,tot;;
long long cnt[300005];
string s;
void newnode(int l)
{
++tot;
for (int i=1;i<=26;i++) next[tot][i]=0;
len[tot]=l;
cnt[tot]=0;
}
int get_fail(int x)
{
while (bz[n-len[x]-1]!=bz[n]) x=fail[x];
return x;
}
void add(char x)
{
int c=x-'a'+1;
bz[++n]=c;
int cur=get_fail(last);
if (!next[cur][c])
{
newnode(len[cur]+2);
fail[tot]=next[get_fail(fail[cur])][c];
next[cur][c]=tot;
}
last=next[cur][c];
cnt[last]++;
}
void count() { for (int i=tot;i>=0;i--) cnt[fail[i]]+=cnt[i]; }
int main()
{
freopen("palindrome.in","r",stdin);
freopen("palindrome.out","w",stdout);
cin>>s;
tot=-1; bz[n]=-1; fail[0]=1;
newnode(0);
newnode(-1);
for (int i=0;i<s.length();i++) add(s[i]);
count();
long long ans=0;
for (int i=2;i<=tot;i++)
{
long long k=cnt[i]*len[i];
if (k>ans) ans=k;
}
printf("%lld",ans);
return 0;
}