看到回文串自然会想到manacher 问题在于怎么统计回文串出现的次数 传说有两种做法 一种是Hash 另一种是 后缀数组 这里我用的Hash
对于一个回文字符串A 我们由去掉它两端字符的回文串A'连一条边 这样就形成了一个树形结构
然后把每一个点为中心的最长回文串 (注意 一定是最长回文串 否则会加重复) 的出现次数加1 这样每一个回文串出现的次数就等于以它为根的子树中串出现次数的总和 dfs更新答案即可
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<map>
#define mp make_pair
#define fir first
#define idx(c) (c-'a'+1)
#define sec second
#define SF scanf
#define PF printf
using namespace std;
typedef long long LL;
typedef unsigned int ULL;
typedef pair<ULL, int> pii;
const int MAXN = 1000000;
const int MOD = 10007;
const int car1 = 2333;
const int car2 = 97;
ULL base1[MAXN+10], hash1[MAXN+10];
int base2[MAXN+10], hash2[MAXN+10];
int len[MAXN+10], cnt = 1, f[MAXN+10], fa[MAXN+10], sum[MAXN+10];
map <pii, int> M;
int n, m;
char s[MAXN+10], str[MAXN+10];
LL ans;
struct Node {
int v, next;
} Edge[MAXN+10];
int adj[MAXN+10], ecnt;
void add(int u, int v) {
Node &e = Edge[++ecnt];
e.v = v; e.next = adj[u]; adj[u] = ecnt;
}
void Read_input() {
SF("%s", str+1);
m = strlen(str+1);
s[0] = '+'; s[++n] = '#';
for(int i = 1; i <= m; i++) {
s[++n] = str[i];
s[++n] = '#';
}
s[++n] = '-';
}
void Hash_init() {
base1[0] = base2[0] = 1;
for(int i = 1; i <= m; i++) {
base1[i] = base1[i-1] * car1; base2[i] = base2[i-1] * car2 % MOD;
}
ULL RK1 = 0; int RK2 = 0;
for(int i = 1; i <= m; i++) {
RK1 = RK1 * car1 + idx(str[i]);
RK2 = RK2 * car2 + idx(str[i]);
hash1[i] = RK1; hash2[i] = (RK2 %= MOD);
}
}
int GetHash(int l, int r) {
ULL key1 = hash1[r] - hash1[l-1] * base1[r-l+1];
int key2 = (hash2[r] - hash2[l-1] * base2[r-l+1] % MOD + MOD) % MOD;
if(l > r) key1 = key2 = 0;
if(M.count(mp(key1, key2))) return M[mp(key1, key2)];
len[++cnt] = r-l+1;
return M[mp(key1, key2)] = cnt;
}
void Manacher_algorithm() {
f[1] = 1;
int P = 1;
M[mp(0, 0)] = 1;
for(int i = 2; i <= n; i++) {
int L, R, u, v;
if(P + f[P] > i) f[i] = min(f[P] + P - i, f[2*P-i]);
else f[i] = 1;
while(s[i-f[i]] == s[i+f[i]]) {
L = R = u = v = 0;
f[i]++;
L = (i - f[i]) / 2 + 1;
R = (i + f[i]) / 2 - 1;
u = GetHash(L+1, R-1);
v = GetHash(L, R);
if(fa[v] == u) continue;
add(u, v); fa[v] = u;
}
L = R = u = v = 0;
L = (i - f[i]) / 2 + 1;
R = (i + f[i]) / 2 - 1;
v = GetHash(L, R);
sum[v]++;
if(f[P] + P < f[i] + i) P = i;
}
}
void dfs(int u) {
for(int i = adj[u]; i; i = Edge[i].next) {
int v = Edge[i].v;
dfs(v);
sum[u] += sum[v];
}
ans = max(ans, 1LL * sum[u] * len[u]);
}
int main() {
Read_input();
Hash_init();
Manacher_algorithm();
dfs(1);
cout << ans;
return 0;
}