洛谷 - P3649 - 回文串 - 回文自动机
https://www.luogu.org/problem/P3649
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Node {
int len, ch[26], fail;
int cnt;
Node(int len = 0) : len(len), fail(0) {
memset(ch, 0, sizeof(ch));
//下面是维护额外信息
cnt=0;
}
};
const int MAXN = 300000;
//PalindromicAutomaton
struct PAM {
Node nd[MAXN + 5];
int len, top, last; // len为字符串长度mtop为节点个数,last为最后插入字符所对应的节点
char s[MAXN + 5];
int getfail(int x) { //沿着fail指针找到第一个回文后缀
while(s[len - nd[x].len - 1] != s[len])
x = nd[x].fail;
return x;
}
PAM() : len(0), top(0), last(0) {
nd[top] = Node(0);
nd[top].fail = 1;
nd[++top] = Node(-1);
nd[top].fail = 0;
s[0] = '$';
}
void extend(char c) {
s[++len] = c;
int now = getfail(last); //找到插入的位置
if(!nd[now].ch[c - 'a']) { //若没有这个节点,则新建并求出它的fail指针
nd[++top] = Node(nd[now].len + 2);
nd[top].fail = nd[getfail(nd[now].fail)].ch[c - 'a'];
nd[now].ch[c - 'a'] = top;
}
last = nd[now].ch[c - 'a'];
//下面是维护额外信息
++nd[last].cnt;
}
} pam;
char s[MAXN + 5];
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
scanf("%s", s);
for(int i = 0; s[i] != '\0'; ++i)
pam.extend(s[i]);
ll ans = 0;
for(int i = pam.top; i >= 2; --i) {
pam.nd[pam.nd[i].fail].cnt += pam.nd[i].cnt;
ans = max(ans, 1ll * pam.nd[i].cnt * pam.nd[i].len);
}
printf("%lld\n", ans);
return 0;
}