在字符串处理领域,寻找最长回文子串是一个经典问题。暴力解法时间复杂度为 O(n³),中心扩展法为 O(n²),而 Manacher算法 能将时间复杂度优化到惊人的 O(n)!本文将用通俗易懂的方式,手把手教你用 Rust语言 实现 Manacher 算法,即使是编程小白也能轻松掌握。
回文是指正着读和反着读都一样的字符串,例如:"aba"、"abba"、"racecar"。我们的目标是:给定一个字符串,找出其中最长的连续回文子串。

虽然中心扩展法已经不错,但它对每个字符都要向两边扩展,存在大量重复计算。Manacher 的核心思想是:利用已知回文信息避免重复计算,通过维护一个“最右边界”和“中心点”,实现线性时间复杂度。
Manacher 算法巧妙地将奇数长度和偶数长度的回文统一处理。方法是在原字符串的每个字符之间插入特殊符号(如 '#'),并在首尾加上不同边界符(如 '^' 和 '$')防止越界。
例如,原字符串 "abba" 会被转换为:
^#a#b#b#a#$这样,所有回文子串都变成了奇数长度,简化了处理逻辑。
下面是我们用 Rust语言 编写的完整 Manacher 算法实现,包含详细注释:
fn manacher(s: &str) -> String { // 步骤1: 预处理字符串 let mut processed = String::from("^"); for ch in s.chars() { processed.push('#'); processed.push(ch); } processed.push('#'); processed.push('$'); let n = processed.len(); let chars: Vec<char> = processed.chars().collect(); // 步骤2: 初始化回文半径数组 let mut p = vec![0; n]; let (mut center, mut right) = (0, 0); let (mut max_len, mut center_index) = (0, 0); // 步骤3: 遍历处理后的字符串 for i in 1..n - 1 { // 利用对称性减少计算 if i < right { let mirror = 2 * center - i; p[i] = (right - i).min(p[mirror]); } // 尝试扩展回文 while chars[i + p[i] + 1] == chars[i - p[i] - 1] { p[i] += 1; } // 更新最右边界和中心 if i + p[i] > right { center = i; right = i + p[i]; } // 记录最长回文 if p[i] > max_len { max_len = p[i]; center_index = i; } } // 步骤4: 从处理后的字符串还原原始回文 let start = (center_index - max_len) / 2; let original_chars: Vec<char> = s.chars().collect(); original_chars[start..start + max_len].iter().collect()}// 测试函数fn main() { let input = "babad"; let result = manacher(input); println!("输入: {}", input); println!("最长回文子串: {}", result);}p:`p[i]` 表示以位置 `i` 为中心的回文半径(不包括中心本身)。center 和右边界 right:记录当前已知最靠右的回文信息。Manacher 算法的时间复杂度为 O(n),空间复杂度也为 O(n),是目前已知解决最长回文子串问题的最优算法。对于处理大规模文本(如基因序列分析、自然语言处理),这种高效性至关重要。
通过本文,你已经掌握了使用 Rust语言 实现 Manacher算法 的完整流程。这项技术不仅能帮你高效解决 最长回文子串 问题,还能提升你在 Rust字符串处理 和算法设计方面的能力。记住,理解算法的核心思想比死记代码更重要——利用对称性避免重复计算,这是 Manacher 算法的精髓所在。
现在,试着用这个算法解决 LeetCode 第5题 “Longest Palindromic Substring” 吧!
本文由主机测评网于2025-12-11发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025126110.html