字符串匹配算法:KMP
Knuth–Morris–Pratt(KMP)是由三位数学家克努斯、莫里斯、普拉特同时发现,所有人们用三个人的名字来称呼这种算法,KMP是一种改进的字符串匹配算法,它的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。它的时间复杂度是 O(m+n)
字符匹配:给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1
在介绍KMP算法之前,我们先看一下另一种暴力算法(BF算法)去解字符匹配应该怎么做

BF算法:时间复杂度O(m*n)
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
#hi是haystack的当前索引
hi = 0
haystackLength = len(haystack)
needleLength = len(needle)
for i in range(haystackLength - needleLength+1):
#每次匹配等于和完整的needle的字符串逐一匹配
if haystack[i:i+needleLength] == needle:
return i
return -1
KMP算法:时间复杂度O(m+n)
KMP构造了一个next列表来对应改位置索引如果匹配失败应该追溯回到什么位置,这样我们讲减少了匹配次数

那么我们如何去构造维护我们的next(最长相同前后缀)
构造方法为:next[i] 对应的下标,为 P[0...i - 1] 的最长公共前缀后缀的长度,令 next[0] = -1。 具体解释如下:
例如对于字符串 abcba:
前缀:它的前缀包括:a, ab, abc, abcb,不包括本身;
后缀:它的后缀包括:bcba, cba, ba, a,不包括本身;
最长公共前缀后缀:abcba 的前缀和后缀中只有 a 是公共部分,字符串 a 的长度为 1
我们通过动态规划来维护next,假设你知道next[0:i-1]位置上所有的回溯值,那么next[i-1]和next[i]相比仅仅多了一个位置,如果这个多的字符可以匹配上,那么next[i]一定等于next[i-1]+1(如下图所示)

那么如果匹配不上呢,匹配不上我们回溯到next[i-1]所需要回溯的位置,直到可以匹配上或到达无法追溯的位置next[0] = -1
@staticmethod
def same_start_end_str(p):
"""
通过needle串来知道每个索引位置对应的最长前后缀
例如ababa的最长前后缀是aba,前后缀是不和needle等长的最长相同前后缀
"""
next = [-1] * (len(p)+1)
si = -1
ei = 0
pl = len(p)
while ei < pl :
if si == -1 or p[si] == p[ei]:
si += 1
ei += 1
next[ei] = si
else:
#无法匹配上,继续向前追溯
si = next[si] return next
那我们有了next就可以取实现我们KMP算法了,完整代码如下
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
next = self.same_start_end_str(needle)
#hi是haystack当前索引,ni是needle当前索引
hi = ni = 0
hl = len(haystack)
nl = len(needle)
while hi < hl and ni < nl:
if ni == -1 or haystack[hi] == needle[ni]:
hi += 1
ni += 1
else:
ni = next[ni] if ni == nl:
return hi - ni
else:
return -1 @staticmethod
def same_start_end_str(p):
"""
通过needle串来知道每个索引位置对应的最长前后缀
例如ababa的最长前后缀是aba,前后缀是不和needle等长的最长相同前后缀
"""
next = [-1] * (len(p)+1)
si = -1
ei = 0
pl = len(p)
while ei < pl :
if si == -1 or p[si] == p[ei]:
si += 1
ei += 1
next[ei] = si
else:
#无法匹配上,继续向前追溯
si = next[si] return next
字符串匹配算法:KMP的更多相关文章
- 字符串匹配算法 - KMP
前几日在微博上看到一则微博是说面试的时候让面试者写一个很简单的字符串匹配都写不出来,于是我就自己去试了一把.结果写出来的是一个最简单粗暴的算法.这里重新学习了一下几个经典的字符串匹配算法,写篇文章以巩 ...
- 字符串匹配算法——KMP算法学习
KMP算法是用来解决字符串的匹配问题的,即在字符串S中寻找字符串P.形式定义:假设存在长度为n的字符数组S[0...n-1],长度为m的字符数组P[0...m-1],是否存在i,使得SiSi+1... ...
- 4种字符串匹配算法:KMP(下)
回顾:4种字符串匹配算法:BS朴素 Rabin-karp(上) 4种字符串匹配算法:有限自动机(中) 1.图解 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R ...
- 字符串匹配算法KMP算法
数据结构中讲到关于字符串匹配算法时,提到朴素匹配算法,和KMP匹配算法. 朴素匹配算法就是简单的一个一个匹配字符,如果遇到不匹配字符那么就在源字符串中迭代下一个位置一个一个的匹配,这样计算起来会有很多 ...
- 字符串匹配算法--KMP字符串搜索(Knuth–Morris–Pratt string-searching)C语言实现与讲解
一.前言 在计算机科学中,Knuth-Morris-Pratt字符串查找算法(简称为KMP算法)可在一个主文本字符串S内查找一个词W的出现位置.此算法通过运用对这个词在不匹配时本身就包含足够的信息 ...
- 字符串匹配算法——KMP算法
处理字符串的过程中,难免会遇到字符匹配的问题.常用的字符匹配方法 1. 朴素模式匹配算法(Brute-Force算法) 求子串位置的定位函数Index( S, T, pos). 模式匹配:子串的定位操 ...
- [Algorithm] 字符串匹配算法——KMP算法
1 字符串匹配 字符串匹配是计算机的基本任务之一. 字符串匹配是什么?举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串& ...
- 字符串匹配算法——KMP、BM、Sunday
KMP算法 KMP算法主要包括两个过程,一个是针对子串生成相应的“索引表”,用来保存部分匹配值,第二个步骤是子串匹配. 部分匹配值是指字符串的“前缀”和“后缀”的最长的共有元素的长度.以“ABCDAB ...
- KMP Algorithm 字符串匹配算法KMP小结
这篇小结主要是参考这篇帖子从头到尾彻底理解KMP,不得不佩服原作者,写的真是太详尽了,让博主产生了一种读学术论文的错觉.后来发现原作者是写书的,不由得更加敬佩了.博主不才,尝试着简化一些原帖子的内容, ...
- 字符串匹配算法-kmp算法
一原理: 部分转自:http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html 字 ...
随机推荐
- AutoCAD 2024下载及安装教程
安装教程 演示操作系统:Windows 11 *安装前请关闭所有杀毒软件,避免报错 1.解压[CAD2024.zip] 2.打开解压的[CAD2024]文件夹,打开[Setup]文件夹,运行[Setu ...
- SkipList原理与实现
机制 链表中查询的效率的复杂度是O(n), 有没有办法提升这个查询复杂度呢? 最简单的想法就是在原始的链表上构建多层索引. 在level 1(最底层为0), 每2位插入一个索引, 查询复杂度便是 O( ...
- Linux 安装:中文manpages
Linux 中文man手册安装 bash 脚本 wget https://src.fedoraproject.org/repo/pkgs/man-pages-zh-CN/manpages-zh-1.5 ...
- HTML超文本标记语言3
三.HTML表单标签 1.form标签 <form> form标签 name=表单名称,action=表单提交的地址,method=表单提交方式:get/post get/post详解: ...
- SQL: Unknown collation: 'utf8mb4_0900_ai_ci'
错误原因 字符集错误,我的版本是5.7,文件中是8.0 解决方案 替换字符集 utf8mb4_0900_ai_ci替换为utf8_general_ci utf8mb4替换为utf8 注意:注释中的部分 ...
- 【入门教程】3202年了,还有人没用stable diffusion画过自己的AI小姐姐吗。
个人绘画作品: 说明 本文主要是讲一下如何安装.使用整合包,以及介绍画真人图片的大模型(介绍的整合包只提供二次元模型,个人不太感兴趣) 通过最简单的介绍帮助大家快速入门,开始画图,不会深入的进行讲解, ...
- 青少年CTF平台-Web-PingME
题目描述 题目难度一颗星,五十分. 解题记录 进入题目中,发现这是一个ping功能 我们用连字符||进行分割两个语句,保证同时运行且输出. Payload为127.0.0.1 || ls 发现有fla ...
- [Go笔记] 基础-01: Golang发展简史、著名项目及基本使用
引言 Golang,又称Go语言,是一门开源的静态类型编译型编程语言.自从2007年由谷歌的罗伯特·格里泽默(Robert Griesemer).罗布·派克(Rob Pike)和肯·汤普森(Ken T ...
- [Arch小贴士]在这里记录一些自己使用的小技巧
哈喽!Arch 目录 0x00 设置开机自启动软件 首先 最后 0x01 ASLR开关 0x00 设置开机自启动软件 首先 首先进入目录/usr/share/applications,找到你要的那个软 ...
- 用ChatGPT三分钟免费做出数字人视频- 提升自媒体魅力
本教程收集于:AIGC从入门到精通教程汇总 操作指引 ChatGPT产生文案=>腾讯智影数字人播报=>粘贴文案=>导出视频. 说明:部分资源只有会员才能用~,非会员可生成5分钟视频. ...