3676: [Apio2014]回文串
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1897 Solved: 822
[ Submit][ Status][ Discuss]
Description
考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出
现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最
大出现值。
Input
输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。
Output
输出一个整数,为逝查回文子串的最大出现值。
Sample Input
【样例输入l】
abacaba
【样例输入2]
www
abacaba
【样例输入2]
www
Sample Output
【样例输出l】
7
【样例输出2]
4
7
【样例输出2]
4
HINT
一个串是回文的,当且仅当它从左到右读和从右到左读完全一样。
在第一个样例中,回文子串有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。
【数据规模与评分】
数据满足1≤字符串长度≤300000。
Source
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 3E5 + 30;
typedef long long LL;
int n,cnt,p,cur[maxn],ch[maxn][26],fail[maxn],Length[maxn],du[maxn];
char a[maxn];
queue <int> Q;
vector <int> v[maxn];
void Read()
{
scanf("%s",a + 1);
n = strlen(a + 1);
cnt = 1;
Length[0] = 0;
Length[1] = -1;
fail[0] = 1;
p = 0;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
Read();
for (int i = 1; i <= n; i++) {
int Nex = a[i] - 'a';
while (a[i] != a[i-Length[p]-1]) p = fail[p];
if (!ch[p][Nex]) {
int tmp = p;
ch[p][Nex] = ++cnt;
Length[cnt] = Length[p] + 2;
if (Length[cnt] > 1) {
p = fail[p];
while (a[i] != a[i-Length[p]-1]) p = fail[p];
p = ch[p][Nex];
}
else p = 0;
v[cnt].push_back(p);
++du[p];
fail[cnt] = p;
p = tmp;
}
p = ch[p][Nex];
++cur[p];
}
for (int i = 0; i <= cnt; i++)
if (!du[i])
Q.push(i);
while (!Q.empty()) {
int k = Q.front(); Q.pop();
for (int i = 0; i < v[k].size(); i++) {
int fa = v[k][i];
cur[fa] += cur[k];
--du[fa];
if (!du[fa]) Q.push(fa);
}
}
LL Ans = 0;
for (int i = 0; i <= cnt; i++)
Ans = max(Ans,1LL*Length[i]*cur[i]);
cout << Ans;
return 0;
}