跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

Manacher 算法详解:线性时间求解最长回文子串

Manacher 算法用于在字符串中高效查找最长回文子串,将中心扩展法的 O(n^2) 优化至 O(n)。核心思想是通过预处理统一奇偶回文串,利用已计算的回文半径和对称性避免重复比较。维护最右回文边界,根据当前点是否在边界内分情况更新半径数组,最终得到最优解。

颠三倒四发布于 2026/3/24更新于 2026/10/2580 浏览
Manacher 算法详解:线性时间求解最长回文子串

Manacher 算法详解:线性时间求解最长回文子串

在字符串处理问题中,寻找最长回文子串是一个经典场景。虽然中心扩展法直观易懂,但其时间复杂度为 O(n²),在处理大规模数据时显得力不从心。Manacher(马拉车)算法通过巧妙的预处理和对称性优化,将时间复杂度降低至 O(n),是解决此类问题的利器。

核心问题定义

我们需要解决两个关联问题:

  1. 找出字符串中所有的回文子串。
  2. 找出其中长度最长的一个。

这两个目标可以通过同一套逻辑同时达成。

基础概念与预处理

什么是回文?

正读和反读都一样的字符串称为回文串。根据长度奇偶性,可分为奇回文串(如 "aba")和偶回文串(如 "abba")。为了统一处理,我们引入以下概念:

  • 回文中心:回文串最中间的位置。
  • 回文半径:从中心到回文串端点的距离(包含中心本身)。

预处理:统一奇偶性

中心扩展法需要分别处理奇数和偶数长度的情况,这增加了代码复杂度。Manacher 算法的核心技巧之一是在字符之间插入特殊分隔符(通常用 #),将所有回文串转化为奇数长度。

例如,原串 abcbaa 经过处理后变为 #a#b#c#b#a#a#。

  • 原奇回文 bab -> #b#a#b#
  • 原偶回文 abba -> #a#b#b#a#

这样处理后,所有回文串的中心都落在某个字符上,无需区分奇偶,只需枚举所有中心点即可。

中心扩展法回顾

在理解 Manacher 之前,先回顾一下基础的暴力解法:以每个位置为中心向两边扩展。

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 算法的关键在于利用已计算的信息加速后续计算。我们维护一个数组 d[i],表示以 i 为中心的最长回文半径。同时,维护一个当前遍历到的最右回文边界 [l, r]。

关键性质

  1. 回文半径数组:d[i] 记录以 i 为中心的回文半径。
  2. 对称性:如果当前位置 i 在最右边界 r 之内,那么它关于中心 l + r - i 的对称点 j 的回文信息可以复用。
  3. 边界更新:只有当新回文串的右端点超过 r 时,才更新 l 和 r。

分类讨论

当我们计算 d[i] 时,分两种主要情况:

  1. i > r:当前点在已知最右回文串之外。此时没有历史信息可用,只能像中心扩展法一样暴力向外扩展,并更新 l 和 r。
  2. i <= r:当前点在已知范围内。利用对称点 j = l + r - i 的信息:
    • 若 d[j] < r - i + 1:说明 j 的回文串完全在 [l, r] 内,由对称性可知 d[i] = d[j]。
    • 若 d[j] > r - i + 1:说明 j 的回文串超出了左边界 l,则 i 的回文串至少延伸到 r,即 d[i] = r - i + 1,之后需继续尝试扩展。
    • 若 d[j] == r - i + 1:边界刚好触及,同样需要尝试继续扩展。

这种策略保证了 r 指针在整个过程中只增不减,从而实现了 O(n) 的时间复杂度。

完整代码实现

下面是一个标准的 C++ 实现模板,可直接用于求解最长回文子串长度。

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

const int N = 2200005; // 根据题目规模调整
string t, s;
int d[N];

// 预处理:添加分隔符
void init() {
    cin >> t;
    s = "#";
    for (char ch : t) {
        s += ch;
        s += '#';
    }
}

// Manacher 算法主逻辑
int manacher() {
    int n = s.size();
    int max_len = 0;
    int l = 0, r = -1; // 当前最右回文边界 [l, r]

    for (int i = 0; i < n; i++) {
        int k = (i > r) ? 1 : min(d[l + r - i], r - i + 1);
        
        // 尝试扩展
        while (i - k >= 0 && i + k < n && s[i - k] == s[i + k]) {
            k++;
        }
        
        d[i] = k;
        
        // 更新最右边界
        if (i + k - 1 > r) {
            l = i - k + 1;
            r = i + k - 1;
        }
        
        // 记录最大回文半径
        max_len = max(max_len, k - 1);
    }
    
    return max_len;
}

int main() {
    init();
    cout << manacher() << endl;
    return 0;
}

总结

Manacher 算法通过预处理消除奇偶差异,并利用回文串的对称性避免了大量重复比较。在实际工程中,如果你需要频繁查询或处理超长字符串的回文特征,这个算法是首选方案。记住,维护好 l 和 r 边界是理解该算法的关键所在。

对于更复杂的变体问题(如查找所有回文子串数量等),可以在上述基础上稍作修改。建议配合洛谷 P3805 等经典题目进行实战练习,加深理解。

目录

  1. Manacher 算法详解:线性时间求解最长回文子串
  2. 核心问题定义
  3. 基础概念与预处理
  4. 什么是回文?
  5. 预处理:统一奇偶性
  6. 中心扩展法回顾
  7. Manacher 算法核心原理
  8. 关键性质
  9. 分类讨论
  10. 完整代码实现
  11. 总结

更多推荐文章

查看全部
  • MyBatisPlus 与 Thymeleaf 全栈分页实战
  • C++备忘录模式:优雅实现对象状态保存与恢复
  • AI 产品经理入门基础与核心知识体系
  • 2025 年秋招 LLM 及多模态模型面试精华
  • Claude Skills 技术详解与实战指南
  • 纯 Java 手写 TopoJSON 生成器:零依赖实现 GeoJSON 转换
  • C++26 反射驱动类型检查重塑代码质量
  • Whisper-large-v3 语音识别服务搭建与使用指南
  • AI 智能客服系统构建方案:选型指南与实战避坑
  • 大模型技术:检索增强生成 RAG 详解
  • 飞书机器人与 Claude Code 交互:从手机指令到 AI 处理的全自动流程
  • 爬虫与大模型结合实践:从基础提取到框架应用
  • C 语言数据结构与算法基础:文件操作、排序查找及链表简介
  • Python 面试高频题:从可变对象到垃圾回收机制
  • 大模型微调七步法:构建垂直领域专用模型
  • AI 产品经理面试核心考点与实战指南
  • 2025 年免费数字人工具评测:五大 AI 平台对比
  • 数据结构顺序表定义、操作与综合应用题解析
  • AI 驱动的产品落地全流程:从需求挖掘到上线管控实战
  • Rust 核心内存安全机制:所有权、借用与生命周期

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online