Manacher 算法详解:线性时间求解最长回文子串
问题背景
在字符串处理中,找出最长的回文子串是一个经典问题。虽然中心扩展法直观易懂,但在处理长字符串时效率较低。Manacher 算法(马拉车算法)通过巧妙的预处理和状态复用,将时间复杂度优化至 O(n)。
基础概念
回文串:正读和反读都一样的字符串。 奇回文串:字符数为奇数,如 "aba"。 偶回文串:字符数为偶数,如 "abba"。 回文半径:从回文中心到端点的距离(包含中心)。
朴素解法:中心扩展
最直接的思路是以每个字符为中心向两边扩展。为了统一处理奇偶回文,通常需要在相邻字符间插入特殊字符(如 '#'),将所有情况转化为奇回文串。
例如 abcbaa 处理后变为 #a#b#c#b#a#a#。
string t, s;
int n;
// 预处理字符串
void init(const string& str) {
s = "#";
for (char ch : str) {
s += ch;
s += '#';
}
n = s.size();
}
// 中心扩展计算最长半径
int expand(int center) {
int d = 1;
while (center - d >= 0 && center + d < n && s[center - d] == s[center + d]) {
d++;
}
return d - 1;
}
此方法的时间复杂度为 O(n²),对于超长字符串可能超时。
优化解法:Manacher 算法
Manacher 算法的核心在于利用已知的回文信息加速计算。我们维护一个当前覆盖最右端的回文区间 [l, r]。
核心逻辑
当计算位置 i 的回文半径 d[i] 时:
- 若 i > r:当前点在最右回文串之外,只能暴力扩展。
- 若 i <= r:利用对称性。设
j为i关于区间中心(l+r)/2的对称点。- 若
d[j] < r - i:说明i的回文串完全包含在 内,直接复制 。
- 若


