基于填充占位符、回文半径镜像对称复制及边界单向扩展,在 $O(N)$ 时间内求解最长回文
最长回文子串问题是指在给定字符串 $S$ 中,寻找长度最长的回文子串。朴素算法以每个点为中心向外双向扩展,最坏时间复杂度为 $O(N^2)$。Manacher 算法利用已知回文的对称性,实现完美的 $O(N)$ 线性复杂度。
#(并在最左/右侧加哨兵 ^ / $),从而将所有奇数长度与偶数长度回文统一化为奇数长度回文。r[i]:以索引 $i$ 为回文中心向外扩展的回文半径(包括 $i$ 本身)。C:当前探索出的能触及最右侧的回文中心。R:中心 C 覆盖的右边界:R = C + r[C]。r[i] 时,若 $i < R$,设 $i$ 关于对称中心 $C$ 的对称镜像点为 $i' = 2 \cdot C - i$。根据回文对称性:
void manacher(string s) {
string t = init(s); // 插入占位符 ^#a#b#a#$
int n = t.length();
vector<int> r(n, 0);
int c = 0, r_boundary = 0; // C 中心与 R 边界
for (int i = 1; i < n - 1; i++) {
int i_mirror = 2 * c - i; // 获取 i 对称的镜像点 i'
if (i < r_boundary) {
// 核心:直接对称复制镜像点的已知半径!
r[i] = min(r_boundary - i, r[i_mirror]);
}
// 双指针向两端暴力扩展
while (t[i - r[i] - 1] == t[i + r[i] + 1]) {
r[i]++;
}
// 若超出当前最右边界,则重定位更新 C 和 R
if (i + r[i] > r_boundary) {
c = i;
r_boundary = i + r[i];
}
}
}