卧薪尝胆,厚积薄发。
APIO2014 回文串
Date: Tue Jan 15 21:16:17 CST 2019 In Category: NoCategory

Description:

求所有回文子串在 $s$ 中出现的次数乘以这个子串的长度的最大值。
$1\leqslant n\leqslant 300000$

Solution:

回文自动机统计一下回文串出现次数。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
int n;
#define MAXN 300010
char c[MAXN];
struct node
{
int tr[26];
int fail,len;
}s[MAXN];
int ptr,last;
int cnt[MAXN];
int newnode(int l){s[ptr].len = l;return ptr++;}
void init()
{
ptr = last = 0;
newnode(0);
newnode(-1);
s[0].fail = 1;
return;
}
int getfail(int i,int p)
{
while(c[i - s[p].len - 1] != c[i])p = s[p].fail;
return p;
}
void extend(int i,int k)
{
int p = getfail(i,last);
if(s[p].tr[k] == 0)
{
int np = newnode(s[p].len + 2);
s[np].fail = s[getfail(i,s[p].fail)].tr[k];
s[p].tr[k] = np;
}
last = s[p].tr[k];
++cnt[last];
return;
}
int main()
{
scanf("%s",c + 1);
n = strlen(c + 1);
init();
for(int i = 1;i <= n;++i)extend(i,c[i] - 'a');
for(int i = ptr;i >= 1;--i)cnt[s[i].fail] += cnt[i];
long long ans = 0;
for(int i = 1;i <= ptr;++i)ans = max(ans,1ll * cnt[i] * s[i].len);
cout << ans << endl;
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡