后缀自动机+manacher
听说本质不同的回文串只有O(n)个
那么用manacher求出所有回文串,然后在sam上查找出现了几次就行了
sam的性质又忘了。。。
manacher也忘了。。。
#include<bits/stdc++.h> using namespace std; const int N = 3e5 + 5; int n, len, pos, mx; long long ans; int c[N << 1], a[N << 1], p[N << 1], fa[N << 1][21], f[N << 1], Pos[N]; char s[N], S[N << 1]; namespace SAM { struct node { int val, par; int ch[26]; } t[N << 1]; int sz = 1, root = 1, last = 1; int nw(int _) { t[++sz].val = _; return sz; } void extend(int c) { int p = last, np = nw(t[p].val + 1); while(p && !t[p].ch[c]) t[p].ch[c] = np, p = t[p].par; if(!p) t[np].par = root; else { int q = t[p].ch[c]; if(t[q].val == t[p].val + 1) t[np].par = q; else { int nq = nw(t[p].val + 1); memcpy(t[nq].ch, t[q].ch, sizeof(t[q].ch)); t[nq].par = t[q].par; t[q].par = t[np].par = nq; while(p && t[p].ch[c] == q) t[p].ch[c] = nq, p = t[p].par; } } last = np; Pos[t[np].val] = np; f[np] = 1; } int query(int l, int r) { int len = r - l + 1, now = Pos[r]; for(int i = 20; i >= 0; --i) if(t[fa[now][i]].val >= len) now = fa[now][i]; return f[now]; } } using namespace SAM; int main() { scanf("%s", s + 1); n = strlen(s + 1); for(int i = 1; i <= n; ++i) extend(s[i] - 'a'); for(int i = 1; i <= sz; ++i) ++c[t[i].val]; for(int i = 1; i <= sz; ++i) c[i] += c[i - 1]; for(int i = 1; i <= sz; ++i) a[c[t[i].val]--] = i; for(int i = sz; i; --i) f[t[a[i]].par] += f[a[i]]; for(int i = 1; i <= sz; ++i) fa[i][0] = t[i].par; for(int j = 1; j <= 20; ++j) for(int i = 1; i <= sz; ++i) fa[i][j] = fa[fa[i][j - 1]][j - 1]; S[0] = '-'; for(int i = 1; i <= n; ++i) { S[++len] = '#'; S[++len] = s[i]; } S[++len] = '#'; S[++len] = '+'; for(int i = 1; i <= len; ++i) { if(i < mx) p[i] = min(mx - i, p[2 * pos - i]); while(S[i - p[i]] == S[i + p[i]]) { ans = max(ans, 1LL * p[i] * query((i - p[i] + 1) >> 1, (i + p[i]) >> 1)); ++p[i]; } if(i + p[i] > mx) { pos = i; mx = i + p[i]; } } printf("%lld ", ans); return 0; }