暂无链接
Palindromes
【问题描述】
纸上得来终觉浅,绝知此事要躬行。
有一个小写字符串 s。我们定义 s 的一个子串的存在值为这个子串在 s 中出现的次数乘以这个子串的长度。
对于给你的这个字符串 s,求所有回文子串中的最大存在值。
【输入格式】
一行,一个由小写字母(a~z)组成的非空字符串 s。
【输出格式】
输出一个整数,表示所有回文子串中的最大存在值。
【输入样例】
abacaba
【输出样例】
7
【样例说明】
在第一个样例中,回文子串有 7 个:a,b,c,aba,aca,bacab,abacaba,其中:
a 出现 4 次,其存在值为 4:1:1=4
b 出现 2 次,其存在值为 2:1:1=2
c 出现 1 次,其存在值为 l:1:l=l
aba 出现 2 次,其存在值为 2:1:3=6
aca 出现 1 次,其存在值为 1=1:3=3
bacab 出现 1 次,其存在值为 1:1:5=5
abacaba 出现 1 次,其存在值为 1:1:7=7
故最大回文子串存在值为 7。
【数据范围】
对 10%10%的输入数据 :1≤|S|≤1001≤|S|≤100。
对 20%20%的输入数据 :1≤|S|≤10001≤|S|≤1000。
对 40%40%的输入数据 :1≤|S|≤100001≤|S|≤10000。
对 70%70%的输入数据 :1≤|S|≤1000001≤|S|≤100000。
对 100%100%的输入数据 :1≤|S|≤3000001≤|S|≤300000。
题解
不愧为最水的一场考试。
很裸的一道回文自动机,增量构造时即可统计每个回文串的出现次数,最后拓扑递推即可得到答案。
代码
#include<bits/stdc++.h>
using namespace std;
const int M=3e5+5;
char ch[M];
int last,odd=1,even=2,tot=2,p,cot[M],son[M][26],len[M],fail[M];
void in(){scanf("%s",ch+1);}
bool go(int v,int x,int pos){return ch[pos-len[v]-1]==ch[pos];}
void add(int x,int pos)
{
for(;!go(last,x,pos);last=fail[last]);
if(son[last][x])last=son[last][x];
else
{
p=last,son[p][x]=++tot,len[tot]=len[p]+2;
if(p==odd)fail[tot]=even;
else{for(p=fail[p];!go(p,x,pos);p=fail[p]);fail[tot]=son[p][x];}
last=tot;
}
++cot[last];
}
void ac()
{
int l=strlen(ch+1);
last=odd,fail[odd]=fail[even]=odd,len[odd]=-1;
for(int i=1;i<=l;++i)add(ch[i]-'a',i);
long long ans=0;
for(int i=tot;i>=1;--i)cot[fail[i]]+=cot[i],ans=max(ans,1ll*cot[i]*len[i]);
printf("%lld",ans);
}
int main(){in();ac();}

本文介绍了一种使用回文自动机构造方法解决寻找字符串中所有回文子串最大存在值的问题,通过增量构造实时统计回文串的出现次数,并最终通过拓扑递推得出答案。
144

被折叠的 条评论
为什么被折叠?



