题解 P3649 【[APIO2014]回文串】
这篇博客介绍的是本题的
张天扬有一篇文章叫做
先说一个显然的事情,一个串倒过来和它正着长得一样,它就是回文串。
然后我分算法流程,正确性,复杂度三部分来说明一下这个做法。
算法流程第一步就是建立
然后我们用反串在
正确性我分成两部分,第一部分是为什么最大存在值会被统计,第二部分是为什么所有统计的答案都是存在值。
我们考虑这个最长回文串
为了保证所有统计的答案都是存在值,我们需要引入一个
复杂度就是建立
这题空间比较小,#define int long long会
#include<bits/stdc++.h>
using namespace std;
#define maxn 600005
#define ll long long
#define Fol(i, j, n) for(register int i = j ; i >= n ; --i)
#define For(i, j, n) for(register int i = j ; i <= n ; ++i)
ll ans;
int n, m, l, k, T, rt, cnt, now = 1, tot, last;
int a[maxn], dp[maxn], fa[maxn], rk[maxn], sa[maxn], len[maxn], num[maxn], vis[maxn], maxpos[maxn], go[maxn][26];
char s[maxn];
inline void insert(int c, int y){
int np = ++tot, x = last;
last = np, dp[np] = 1, maxpos[np] = y, len[np] = len[x] + 1;
for( ; !go[x][c] && x ; x = fa[x]) go[x][c] = np;
if(!x) return fa[np] = rt, void();
int nq = go[x][c];
if(len[nq] == len[x] + 1) fa[np] = nq;
else{
int q = ++tot;
memcpy(go[q], go[nq], sizeof(go[q]));
len[q] = len[x] + 1, fa[q] = fa[nq], fa[nq] = fa[np] = q;
for( ; go[x][c] == nq ; x = fa[x]) go[x][c] = q;
}
}
int main(){
scanf("%s", s + 1), n = strlen(s + 1), rt = last = ++tot;
For(i, 1, n) insert(s[i] - 'a', i);
For(i, 1, tot) num[len[i]]++;
For(i, 1, n) num[i] += num[i - 1];
For(i, 1, tot) a[--num[len[i]]] = i;
Fol(i, tot, 1) dp[fa[a[i]]] += dp[a[i]], maxpos[fa[a[i]]] = max(maxpos[fa[a[i]]], maxpos[a[i]]);
Fol(i, n, 1){
for( ; now && !go[now][s[i] - 'a'] ; now = fa[now], l = len[now]);
if(go[now][s[i] - 'a']) ++l, now = go[now][s[i] - 'a'];
if(maxpos[now] - l < i){
if(i <= maxpos[now]) ans = max(ans, 1ll * dp[now] * (maxpos[now] - i + 1));
for(int p = fa[now] ; p && !vis[p] ; p = fa[p]){
vis[p] = 1;
if(maxpos[p] - len[p] < i && i <= maxpos[p]) ans = max(ans, 1ll * dp[p] * (maxpos[p] - i + 1));
}
}
}
printf("%lld", ans);
return 0;
}