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

KMP 字符串匹配算法原理与 next 数组推导

KMP 算法通过预处理模式串生成 next 数组,实现主串指针不回溯的线性时间复杂度匹配。文章详细解析了 next 数组的定义、计算逻辑及手动推导过程,并提供了 Python 代码实现示例,涵盖从基础原理到具体步骤的完整说明。

颠三倒四发布于 2026/2/28更新于 2026/10/25106 浏览
KMP 字符串匹配算法原理与 next 数组推导

KMP(Knuth-Morris-Pratt)算法是一种高效的字符串匹配算法,其核心思想是避免主串指针回溯,通过预处理模式串构造 next 数组,使得在发生字符不匹配时,能够快速调整模式串的匹配位置。

代码实现

def compute_next(pattern):
    """计算模式串的 next 数组"""
    m = len(pattern)
    next_arr = [-1] * m  # 初始化 next 数组,第一个元素为 -1
    j = -1  # 指向前缀末尾(初始为 -1)
    for i in range(1, m):  # i 指向后缀末尾
        while j != -1 and pattern[i] != pattern[j + 1]:
            j = next_arr[j]
        if pattern[i] == pattern[j + 1]:
            j += 1
        next_arr[i] = j
    return next_arr

def kmp_search(text, pattern):
    """KMP 算法主函数:返回模式串在主串中首次出现的起始下标,未找到返回 -1"""
    if not pattern:
        return 0
    n, m = len(text), len(pattern)
    next_arr = compute_next(pattern)
    j = -1  # 模式串匹配指针(当前已匹配到的位置)
    for i in range(n):  # 遍历主串
        while j != -1 and text[i] != pattern[j + 1]:
            j = next_arr[j]  # 失配时利用 next 跳转
         text[i] == pattern[j + ]:
            j += 
         j == m - :  
             i - m +   
     -  


text = 
pattern = 
next_table = compute_next(pattern)
(, next_table)  
pos = kmp_search(text, pattern)
()
if
1
1
if
1
# 完全匹配
return
1
# 返回起始位置
return
1
# 匹配失败
# 示例使用
"abacbababbcbc"
"abababb"
print
"Next 数组:"
# 输出:[-1, 0, 0, 1, 2, 3, 4]
print
f"模式串 '{pattern}' 在主串中的起始位置:{pos}"

解析说明

  • next 数组含义:next[j] 表示模式串前 j+1 个字符中最长相等前后缀的长度减一(即回退位置)。例如 "abababb" 的 next = [-1, 0, 0, 1, 2, 3, 4]。
  • 匹配过程:当 text[i] != pattern[j] 时,令 j = next[j],无需移动 i,从而保证时间复杂度为 O(n+m)。
  • 效率优势:相比朴素算法每次失配都需回溯主串指针,KMP 实现了主串只遍历一次。

手动推导 next 数组

手动推导 KMP 算法中模式串的 next 数组,核心是对每个位置 j,求其子串 pattern[0…j] 的最长相等真前缀与真后缀的长度,并将该长度减一作为 next[j](即回退到的位置下标)。我们以模式串 "abaabc" 为例,逐步推导其 next 数组。

✅ 模式串:"abaabc"
j(下标)012345
字符abaabc

我们将逐位计算 next[j]:

🔹 j = 0
  • 子串:"a"
  • 无真前缀和真后缀 → 最长相等前后缀长度为 0
  • next[0] = -1 (规定第一个值为 -1)

✅ next[0] = -1

🔹 j = 1
  • 子串:"ab"
  • 前缀集合:{"a"}
  • 后缀集合:{"b"}
  • 相等前后缀:空 → 长度为 0
  • next[1] = 0

✅ next[1] = 0

🔹 j = 2
  • 子串:"aba"
  • 前缀:{"a", "ab"}
  • 后缀:{"a", "ba"}
  • 共同部分:"a" → 长度为 1
  • 所以最长相等前后缀长度为 1 → 下标为 0
  • next[2] = 0(因为要记录的是前缀最后一个字符的下标)

✅ next[2] = 0

🔹 j = 3
  • 子串:"abaa"
  • 前缀:{"a", "ab", "aba"}
  • 后缀:{"a", "aa", "baa"}
  • 共同部分:"a" → 长度为 1 → 对应下标 0
  • next[3] = 0

✅ next[3] = 0

🔹 j = 4
  • 子串:"abaab"
  • 前缀:{"a", "ab", "aba", "abaa"}
  • 后缀:{"b", "ab", "aab", "baab"}
  • 共同部分:"ab" → 长度为 2 → 对应下标 1
  • next[4] = 1

✅ next[4] = 1

🔹 j = 5
  • 子串:"abaabc"
  • 前缀:{"a", "ab", "aba", "abaa", "abaab"}
  • 后缀:{"c", "bc", "abc", "aabc", "baabc"}
  • 没有公共非空相等前后缀?检查:
    • "a" vs "c" → 不等
    • "ab" vs "bc" → 不等
    • …
    • 仅可能匹配长度为 0
  • 实际上唯一可能的是长度为 0
  • next[5] = 0

✅ next[5] = 0

📊 最终结果
j012345
字符abaabc
next[j]-100010
✅ 总结推导方法(手动步骤)
  1. next[0] = -1 固定。
  2. 对于每个后续位置 j ≥ 1:
    • 考察子串 pattern[0..j]
    • 找出它的所有真前缀和真后缀
    • 找出其中最长的相等前后缀
    • 记录这个最长前缀的最后一个字符的下标 → 即为 next[j]
  3. 可用递推思想辅助:若已知前面的 next 值,可通过类 KMP 方式模拟构建。
# 验证代码
def compute_next(pattern):
    m = len(pattern)
    next_arr = [-1] * m
    j = -1
    for i in range(1, m):
        while j != -1 and pattern[i] != pattern[j + 1]:
            j = next_arr[j]
        if pattern[i] == pattern[j + 1]:
            j += 1
        next_arr[i] = j
    return next_arr

print(compute_next("abaabc"))  # 输出:[-1, 0, 0, 0, 1, 0] ✔️

目录

  1. 代码实现
  2. 示例使用
  3. 解析说明
  4. 手动推导 next 数组
  5. ✅ 模式串:"abaabc"
  6. 🔹 j = 0
  7. 🔹 j = 1
  8. 🔹 j = 2
  9. 🔹 j = 3
  10. 🔹 j = 4
  11. 🔹 j = 5
  12. 📊 最终结果
  13. ✅ 总结推导方法(手动步骤)
  14. 验证代码

更多推荐文章

查看全部
  • Python FastAPI 入门教程:新手快速上手指南
  • 告别随意修改 State:Immutable.js 实战与避坑指南
  • SpringBoot+Vue 高校疫情防控管理系统设计与实现
  • Python Flask 职位数据采集与数据分析系统设计与实现
  • AI 辅助开发:基于 DeepSeek 构建贪吃蛇游戏实战
  • C++ string 类全面解析
  • C++备忘录模式:优雅实现对象状态保存与恢复
  • 大模型入门教程:基础原理、微调技术与实战指南
  • Strudel:在浏览器里做实时算法音乐
  • AI 产品经理入门基础与核心知识体系
  • Three.js 结合 C# 桌面应用的十万级粒子性能实测
  • Android 插件化开发:代理 Activity 模式详解
  • 数据结构核心:KMP 算法、Trie 树与并查集详解
  • 2025 年秋招 LLM 及多模态模型面试精华
  • CentOS 7 环境下安装 JDK 1.8 及解决 wget 命令缺失问题
  • OpenClaw 集成 GitHub Copilot GPT-5.4 故障修复指南
  • B 站网页版自动字幕脚本:快捷键控制与自动开启
  • Claude Skills 技术详解与实战指南
  • AI 时代:如何构建高竞争力的产品经理能力模型
  • Llama-3 接入 verl 框架的 GRPO 训练实践

相关免费在线工具

  • 加密/解密文本

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

  • Gemini 图片去水印

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

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

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

  • Base64 文件转换器

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

  • Markdown转HTML

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