0%

Manacher

模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
char s[maxn << 1] = "##";
int n, hw[maxn << 1];
int l[maxn << 1], r[maxn << 1];
void manacher(char* a) {//字符串a下标从0开始
int len = strlen(a);
for (int i = 0; i < len; i++) {
s[i * 2 + 2] = a[i];
s[i * 2 + 3] = '#';
}
n = len * 2 + 2;
s[n] = 0;
int maxr = 0, m = 0;
for (int i = 1; i < n; i++) {
if (i < maxr)
hw[i] = min(hw[m * 2 - i], hw[m] + m - i);
else
hw[i] = 1;
while (s[i + hw[i]] == s[i - hw[i]]) hw[i]++;
if (hw[i] + i > maxr) {
m = i;
maxr = hw[i] + i;
}
}
}

例题

最长双回文串

https://www.luogu.com.cn/problem/P4555

题意

在给定的字符串中找到两个相邻的回文串,长度最长

思路

将Manacher处理后的"#"当作两个回文串的连接点

注意这个处理步骤:

1
2
l[i + hw[i] - 1] = max(l[i + hw[i] - 1], hw[i] - 1);
r[i - hw[i] + 1] = max(r[i - hw[i] + 1], hw[i] - 1);

还有这个步骤:

1
2
3
4
for (int i = 3; i <= n;i+=2)
r[i] = max(r[i], r[i - 2] - 2);
for (int i = n; i >= 1;i-=2)
l[i] = max(l[i], l[i + 2] - 2);

代码 : https://xlorpaste.cn/jtcnhg