当前位置: 首页 > news >正文

【Python】KMP算法

KMP算法详解:高效字符串匹配的终极指南

本文通过大量图表和清晰概念,深入解析KMP算法的核心原理与实现细节

算法定义在这里插入图片描述

KMP算法(Knuth-Morris-Pratt算法)是一种高效的字符串匹配算法,由D.E.Knuth、J.H.Morris和V.R.Pratt于1977年联合发表。该算法通过消除主串指针的回溯,将字符串匹配的时间复杂度优化到O(n+m)

核心思想

传统暴力匹配的问题

主串: A B A B A B C
模式: A B A B C暴力匹配过程:
1. A B A B A B CA B A B C ✗ (第5个字符不匹配)2. A B A B A B C  A B A B C ✗ (完全重新开始)3. A B A B A B CA B A B C ✗4. A B A B A B CA B A B C ✓

问题:每次失配都从模式串头部重新开始,效率低下

KMP的智能跳跃

主串: A B A B A B C
模式: A B A B CKMP匹配过程:
1. A B A B A B CA B A B C ✗ (第5个字符不匹配)2. A B A B A B C  A B A B C ✓ (利用已匹配信息直接跳跃)

核心:利用已匹配部分的信息,避免主串指针回溯

关键概念解析

1. 部分匹配表(next数组)

定义:对于模式串P,next[i]表示子串P[0:i]最长相等真前缀和真后缀的长度。

构建过程图解(模式串:“ABABC”)
模式串: A B A B C
索引:   0 1 2 3 4next数组构建:
i=0: "A"前缀: []    后缀: []      → 长度: 0 → next[0]=0i=1: "AB"  前缀: ["A"] 后缀: ["B"]    → 无公共 → next[1]=0i=2: "ABA"前缀: ["A","AB"] 后缀: ["A","BA"] 公共: "A" → 长度:1 → next[2]=1i=3: "ABAB"前缀: ["A","AB","ABA"]后缀: ["B","AB","BAB"] 公共: "AB" → 长度:2 → next[3]=2i=4: "ABABC"前缀: ["A","AB","ABA","ABAB"]后缀: ["C","BC","ABC","BABC"]无公共 → next[4]=0

最终next数组: [0, 0, 1, 2, 0]

2. 真前缀与真后缀

字符串: "ABAB"真前缀: "A", "AB", "ABA"  (不包含自身)
真后缀: "B", "AB", "BAB"  (不包含自身)最长公共: "AB" (长度=2)

算法执行流程

完整匹配过程演示

主串 S: “ABABABC”
模式串 P: “ABABC”
next数组: [0, 0, 1, 2, 0]

步骤1: 初始状态
S: A B A B A B C↑i=0
P: A B A B C↑j=0
状态: S[0]=P[0] ✓ → i=1, j=1步骤2: 
S: A B A B A B C↑i=1  
P: A B A B C↑j=1
状态: S[1]=P[1] ✓ → i=2, j=2步骤3:
S: A B A B A B C↑i=2
P: A B A B C↑j=2  
状态: S[2]=P[2] ✓ → i=3, j=3步骤4:
S: A B A B A B C↑i=3
P: A B A B C↑j=3
状态: S[3]=P[3] ✓ → i=4, j=4步骤5: 失配处理 ✗
S: A B A B A B C↑i=4
P: A B A B C↑j=4
状态: S[4]≠P[4] ✗ → j=next[j-1]=next[3]=2步骤6: 跳跃后继续
S: A B A B A B C↑i=4
P:     A B A B C↑j=2
状态: S[4]=P[2] ✓ → i=5, j=3步骤7:
S: A B A B A B C↑i=5
P:     A B A B C↑j=3
状态: S[5]=P[3] ✓ → i=6, j=4步骤8:
S: A B A B A B C↑i=6
P:     A B A B C↑j=4  
状态: S[6]=P[4] ✓ → 匹配成功!

代码实现

Python实现

class Solution:def getNext(self, next_arr, s):j = -1next_arr[0] = jfor i in range(1, len(s)):while j >= 0 and s[i] != s[j+1]:j = next_arr[j]if s[i] == s[j+1]:j += 1next_arr[i] = jdef strStr(self, haystack: str, needle: str) -> int:if not needle:return 0next_arr = [0] * len(needle)self.getNext(next_arr, needle)j = -1for i in range(len(haystack)):while j >= 0 and haystack[i] != needle[j+1]:j = next_arr[j]if haystack[i] == needle[j+1]:j += 1if j == len(needle) - 1:return i - len(needle) + 1return -1# 测试代码
if __name__ == "__main__":solution = Solution()S = 'ABABABC'W = 'ABABC'print(solution.strStr(S, W))  # 应该输出 2# 更多测试用例print(solution.strStr("hello", "ll"))  # 应该输出 2print(solution.strStr("aaaaa", "bba"))  # 应该输出 -1print(solution.strStr("", ""))  # 应该输出 0

算法复杂度分析

操作时间复杂度空间复杂度
构建next数组O(m)O(m)
匹配过程O(n)O(1)
总计O(n+m)O(m)

对比传统算法

  • 暴力匹配:O(n×m)
  • KMP算法:O(n+m)
http://www.dtcms.com/a/500824.html

相关文章:

  • 利用大平台做网站邯郸网站建设选哪家好
  • 网站备案需要建设好网站吗百度域名地址查询
  • MyBatis 工作原理
  • 企业网站建设找哪家公众号背景图怎么制作
  • 协会宣传网站开发方案汕头网站时优化
  • 东莞餐饮网站建设济源市工程建设监理所网站
  • 网站群建设成本分析网页设计重庆
  • 抽奖网站做的下去吗北京 手机网站建设
  • php语言做购物网站广州公司注册无地址
  • 网站定制开发流程和功能wap 2.0的网站
  • 网站建设产品展示型的专业版式设计网站
  • 购物网站开发中查看订单的实现逻辑网站发布和推广
  • CentOS 7 虚拟IP配置指南:使用传统network-scripts实现高可用
  • 网站建设商务代表工作总结代账公司注册条件
  • 苏州企业网站建设专家番禺做网站多少钱
  • icp备案 网站负责人福建网站建设价格
  • 在AGX上安装opencv4的cuda版本,带有GPU加速的opencv库
  • 深圳专业做网站排名多少钱无锡网页制作服务
  • 【学习系列】SAP RAP 8:行为定义-Authorization Control
  • 河北建设厅网站修改密码在哪网站建设百度推广总结
  • Java Web API 开发完整指南
  • 网站建设与管理复习知识点购物网站怎么创建
  • IEEE 802.11无线wifi帧结构
  • [SCADE编译原理] 时钟分析原理(2003)
  • 做网站的市场细分陶瓷网站制作
  • 毕设做网站具体步骤网站开发模板
  • Vue3与Vue2中使用对比
  • 做电子的外单网站有哪些的优质的成都网站建设推
  • 手机网站建设的现状河南省住房和建设厅网站
  • 企业官方网站建设费用网站免费源码