回文树/回文自动机(Palindrome Tree / Palindrome Automaton)
该实现的常数很大。
#include <cstdio>
#include <cstring>
#include <algorithm>
const int MAXN = 300005;
const int CHAR_SET = 26;
struct PalinT {
struct Node {
Node *c[CHAR_SET], *fail;
int len, cnt;
Node(int len = 0) : len(len), cnt(0), c(), fail(NULL) {}
} *even, *odd, *last, _pool[MAXN], *_curr;
char str[MAXN];
int size;
PalinT() : str() {
_curr = _pool;
last = even = new (_curr++) Node;
even->fail = odd = new (_curr++) Node(-1);
odd->fail = odd;
str[size = 0] = -1;
}
Node *extend(int c) {
str[++size] = c;
Node *v = last;
for (; str[size - v->len - 1] != str[size]; v = v->fail) {}
Node *u = v->c[c];
if (!u) {
u = v->c[c] = new (_curr++) Node(v->len + 2);
Node *p = v->fail;
for (; str[size - p->len - 1] != str[size]; p = p->fail) {}
u->fail = v == odd ? even : p->c[c];
}
u->cnt++;
return last = u;
}
void build(char *begin, char *end) {
for (char *p = begin; p != end; p++) extend(*p - 'a');
}
void count() {
for (Node *p = _curr - 1; p >= _pool; p--) p->fail->cnt += p->cnt;
}
} palinT;
int main() {
static char s[MAXN];
scanf("%s", s);
int n = strlen(s);
palinT.build(s, s + n);
palinT.count();
long long ans = 0;
for (PalinT::Node *p = palinT._pool; p != palinT._curr; p++)
ans = std::max(ans, (long long) p->len * p->cnt);
printf("%lld\n", ans);
return 0;
}