Manacher
# Manacher
# 引入
Manacher 算法可以在 的时间内求出一个字符串中的最长回文串
先需要改造原字符串,在字符之间和两端插入 #
,改造后,都变成了奇回文串,并把 改成 $
那么,aba
就改造成 $#a#b#a#
了
我们定义回文半径 表示以 为中心的最长回文串的长度的一半,叫回文半径
加速盒子 ,算法过程中我们维护右端点最靠右的最长回文串,利用盒子,借助之前的状态来加速计算的状态,具体的来说,盒内的 可以利用对称点的 值来转移,盒外暴力
# 实现
计算前 个 函数,维护盒子
- 如果 ,则 的对称点为
- 若 ,则
- 若 ,则令 ,从 往后暴力枚举
- 如果 ,则从 开始暴力枚举
- 求出 后,如果 ,则更新盒子
auto manacher(string a) {
string s = "$#";
for (int i = 0; i < a.size(); i++)
s += a[i], s += '#';
vector<int> d(s.size());
d[1] = 1;
for (int i = 2, l, r = 1; i < s.size(); i++) {
if (i <= r) d[i] = min(r - i + 1, d[r - i + l]);
while (s[i - d[i]] == s[i + d[i]]) d[i] ++;
if (i + d[i] - 1 > r)
l = i - d[i] + 1, r = i + d[i] - 1;
}
return d;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
上次更新: 2024/09/14, 12:53:16