学习博客:
字符串哈希:https://blog.csdn.net/pengwill97/article/details/80879387 (好像求区间有点小问题)
马拉车Manacher: https://blog.csdn.net/Clove_unique/article/details/53750322
回文自动机/回文树:
https://blog.csdn.net/Clove_unique/article/details/53750322
https://ksmeow.moe/palindromic_tree/
https://www.cnblogs.com/bztMinamoto/p/9630617.html
https://www.cnblogs.com/nietzsche-oier/p/6935081.html
模板题练习:
字符串哈希:P3370 【模板】字符串哈希
马拉车Manacher:POJ 3974 Palindrome
回文自动机:P3649 [APIO2014]回文串
模板:
Manacher:
int d, len, c, r, ansc, ansr, p[maxn<<1];
///r-1是最大回文串能到达的最右端的值
char x[maxn], m[maxn<<1];
void manacher() {
c = r = ansc = ansr = 0;
len = strlen(x + 1);
d = len * 2 + 1, m[0] = '@', m[1] = '#';
for(int i = 1; i <= len; i++)
m[i * 2] = x[i], m[i * 2 + 1] = '#';
m[d + 1] = '\0';
for(int i = 1; i <= d; i++) {
p[i] = r > i ? min(p[2 * c - i], r - i) : 1;
while(m[i + p[i]] == m[i - p[i]])
p[i]++;
if(r < i + p[i])
c = i, r = i + p[i];
if(ansr < p[i])
ansr = p[i], ansc = i;
}
}
回文自动机:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 5;
char s[maxn];
struct PAM {
int d, last;
///d为建立回文自动机的字符串长度
///last上一次插入字符串停在的节点
struct Node {
int cnt, len, fail, child[27];
Node(int len, int fail): len(len), fail(fail), cnt(0) {
memset(child, 0, sizeof(child));
};
};
vector<Node>st;
inline int newnode(int len, int fail = 0) {
///新建一个点
st.emplace_back(len, fail);
return st.size() - 1;
}
inline int getfail(int x, int n) {
///x为当前点的编号,n为插入字符的位置
while(s[n] != s[n - st[x].len - 1])
x = st[x].fail;
return x;
}
inline void Insert(int i) {
int c = s[i] - 'a';
int cur = getfail(last, i);
///不存在这条边,新增节点
if(!st[cur].child[c]) {
int p = newnode(st[cur].len + 2, st[getfail(st[cur].fail, i)].child[c]);
st[cur].child[c] = p;
}
///更新last,数量+1
st[last = st[cur].child[c]].cnt++;
}
void init(char *s) {
st.clear();
d = strlen(s + 1);
s[0] = 0;
///建立偶串和奇串的根和fail
/// 偶的fail->奇
newnode(0, 1), newnode(-1);
last = 0;
for(int i = 1; i <= d; i++)
Insert(i);
}
long long get_all() {
long long ans = 0;
for(int i = st.size() - 1; i >= 0; i--)
st[st[i].fail].cnt += st[i].cnt;
for(int i = 2; i < st.size(); i++)
ans = max(ans, 1LL * st[i].len * st[i].cnt);
return ans;
}
} pam;
int main() {
scanf("%s", s + 1);
pam.init(s);
printf("%lld\n", pam.get_all());
return 0;
}