字符串匹配的KPM算法

article/2025/10/9 7:36:03

转至:http://www.ruanyifeng.com/blog/2013/05/Knuth–Morris–Pratt_algorithm.html

字符串匹配是计算机的基本任务之一。

举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"?

许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一。它以三个发明者命名,起头的那个K就是著名科学家Donald Knuth。

这种算法不太容易理解,网上有很多解释,但读起来都很费劲。直到读到Jake Boxer的文章,我才真正理解这种算法。下面,我用自己的语言,试图写一篇比较好懂的KMP算法解释。

1.

首先,字符串"BBC ABCDAB ABCDABCDABDE"的第一个字符与搜索词"ABCDABD"的第一个字符,进行比较。因为B与A不匹配,所以搜索词后移一位。

2.

因为B与A不匹配,搜索词再往后移。

3.

就这样,直到字符串有一个字符,与搜索词的第一个字符相同为止。

4.

接着比较字符串和搜索词的下一个字符,还是相同。

5.

直到字符串有一个字符,与搜索词对应的字符不相同为止。

6.

这时,最自然的反应是,将搜索词整个后移一位,再从头逐个比较。这样做虽然可行,但是效率很差,因为你要把"搜索位置"移到已经比较过的位置,重比一遍。

7.

一个基本事实是,当空格与D不匹配时,你其实知道前面六个字符是"ABCDAB"。KMP算法的想法是,设法利用这个已知信息,不要把"搜索位置"移回已经比较过的位置,继续把它向后移,这样就提高了效率。

8.

怎么做到这一点呢?可以针对搜索词,算出一张《部分匹配表》(Partial Match Table)。这张表是如何产生的,后面再介绍,这里只要会用就可以了。

9.

已知空格与D不匹配时,前面六个字符"ABCDAB"是匹配的。查表可知,最后一个匹配字符B对应的"部分匹配值"为2,因此按照下面的公式算出向后移动的位数:

  移动位数 = 已匹配的字符数 - 对应的部分匹配值

因为 6 - 2 等于4,所以将搜索词向后移动4位。

10.

因为空格与C不匹配,搜索词还要继续往后移。这时,已匹配的字符数为2("AB"),对应的"部分匹配值"为0。所以,移动位数 = 2 - 0,结果为 2,于是将搜索词向后移2位。

11.

因为空格与A不匹配,继续后移一位。

12.

逐位比较,直到发现C与D不匹配。于是,移动位数 = 6 - 2,继续将搜索词向后移动4位。

13.

逐位比较,直到搜索词的最后一位,发现完全匹配,于是搜索完成。如果还要继续搜索(即找出全部匹配),移动位数 = 7 - 0,再将搜索词向后移动7位,这里就不再重复了。

14.

下面介绍《部分匹配表》是如何产生的。

首先,要了解两个概念:"前缀"和"后缀"。 "前缀"指除了最后一个字符以外,一个字符串的全部头部组合;"后缀"指除了第一个字符以外,一个字符串的全部尾部组合。

15.

"部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度。以"ABCDABD"为例,

  - "A"的前缀和后缀都为空集,共有元素的长度为0;

  - "AB"的前缀为[A],后缀为[B],共有元素的长度为0;

  - "ABC"的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;

  - "ABCD"的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;

  - "ABCDA"的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为"A",长度为1;

  - "ABCDAB"的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为"AB",长度为2;

  - "ABCDABD"的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。

16.

"部分匹配"的实质是,有时候,字符串头部和尾部会有重复。比如,"ABCDAB"之中有两个"AB",那么它的"部分匹配值"就是2("AB"的长度)。搜索词移动的时候,第一个"AB"向后移动4位(字符串长度-部分匹配值),就可以来到第二个"AB"的位置。


http://chatgpt.dhexx.cn/article/606sf6nN.shtml

相关文章

学习报告:kmp

我们应该都知道一个这样子的题目, 输入两个字符串,求一个字符串在另一个字符串出现的次数,我们可以使用两个for循环来解决这个事,可是这个方法的时间要太久了,所以就需要我们kmp,我们先来介绍一个表 这个表…

图解+原理推导完全读懂KPM算法

文章目录 串定长顺序存储方式串的模式匹配BF算法KMP算法KMP算法原理KMP算法实现求模式串T的next值算法 时间复杂度分析BF算法分析KMP算法分析KMP算法与BF算法比较 串定长顺序存储方式 我们显式地在串的索引为0处存储串长。 #define MAXSTRLEN 255 // 用户可在255以内定义最…

英文打字速度180kpm

刚测了一下打字; 基本在180kpm左右; 作为程序员应该足够用了; 我看了一下kpm的意思; 请问英文的打字速度的KPM要多少才是一般录入员的速度呢?我177KPM是高还是低呀??? - ...... 一分钟要打60个字以上,大约要打420kpm,你的17…

4. 串的【朴素模式匹配算法】、【KPM算法:求next数组、nextval数组】

串的模式匹配:在主串中,找到与模式串相同的子串,并返回其所在位置。 其实就是给出一个串abc,找到abc在主串的位置【abc都要匹配】 模式串:给出一个串abc 子串:主串中的abc【可能没有】 文章目录 1. 串的朴素模式匹配算法1.1 方法一:用k记录位置1.2 方法二:不用k2. KPM算…

KPM算法详解(Next数组)

由LeetCode_28引发的思考 最开始用了剪枝思想的朴素解法虽然做出来了,在看答案的时候发现了有一种叫KMP的算法专门就是解决快速查找匹配串问题的,进行了深入的学习。 下面的图源自宫水三叶的解答 我们有两个字符串,在原串中寻找是否有匹配串。…

【C#】KPM算法解决字符串匹配问题

KPM算法解决字符串匹配问题 什么是KPM算法步骤Ⅰ根据《最大长度表》部分匹配表(next)寻找最长前缀后缀 Ⅱ 根据 部分匹配表 进行匹配 代码实现 什么是KPM算法 Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个…

串的匹配 (KPM算法由来引导)

前言: 引入 KPM 算法的前提是 , B-F算法中,匹配失败后不必完全从头再来 , 找到可以利用的信息 , 可以进行跳跃性匹配 下面 , 我们对字符串匹配的一些思路进行剖析: 开始匹配的操作 ,我们会让 目标串 s , 和 模式串进行对齐,就像如图所示: 我们当然是从串 t 的头结点开始对比 对…

KPM匹配算法

KPM匹配算法 不管在工作中还是学习中经常会遇到串的模式匹配,一般来说,串的模式匹配算法主要是两种【朴素模式匹配和KPM模式匹配】一种改良【KPM的改良】,下面先看一下朴素模式匹配:朴素模式匹配主要思想比较简单也比较粗暴&…

KPM算法

算法 字符串匹配之朴素算法和KMP算法及JAVA代码实现 2017年06月02日 10:31:12 阅读数:941 暴力匹配算法 假设现在我们面临这样一个问题:有一个文本串S,和一个模式串P,现在要查找P在S中的位置,怎么查找呢&#xff1…

Python KPM算法

知识点说明: 先说前缀,和后缀吧 比如有一个串:abab 则在下标为3处的(前缀和后缀都要比下标出的长度小1,此处下标为3出的长度是4) 前缀为:a,ab,aba 后缀为:b,ba,bab 一、要获取…

KPM算法——数据结构|复习局|串|复杂模式匹配算法|二维数组解决KPM

数据结构复习局——KPM算法 何为KPM?事先规则状态匹配dp——状态转移图状态X获得dp数组值看看图再理解下 写在前面: 本文仅为作者个人学习记录,详细具体内容参考自知乎大佬labuladong 👈点击与大佬🤺击剑🤺…

KMP算法原理及实例

KMP是为了解决串的匹配问题。 一、基础知识 1、概念 1.串的匹配问题:就是在一个长的主串s中找到另一个的短的子串t。 2.目标串(主串\文本串):被匹配的母串,串s被称为目标串。 3.模式串(子串)&#xff1a…

KPM算法思想及实现

一、比较暴力算法和KMP算法 1、暴力算法: 双指针遍历主串和子串,当发现主串和子串不匹配时,双指针同时回溯 2、KMP算法: 双指针遍历主串和子串,当发现主串和子串不匹配时,通过比较子串的next数组只回溯…

正定矩阵的性质

正定矩阵的定义:若矩阵A是n阶方阵,并且它的二次型大于0,即,则矩阵A是正定矩阵。 正定矩阵的性质: 正定矩阵的所有特征值都为正数。正定矩阵行列式为正数两个正定矩阵的和为正定矩阵(两个正定矩阵的乘积不…

顺序主子式

设A为 阶矩阵,子式 称为A的i阶顺序主子式。 [1] 对于 阶的矩阵A,其共有n阶顺序主子式,即矩阵A的顺序主子式由 共n个行列式按顺序排列而成。

【矩阵论笔记】平方根分解

定义 例子 首先判断顺序主子式。 R矩阵每一行除以对角元 平方根分解推导 因为A的分解是唯一的,可以得到 L R T LR^{T} LRT 例题 待定系数法

MATLAB_数值计算_用平方根法解线性方程组—(Cholesky分解)

利用对称正定矩阵的乔累斯基分解求解对称正定方程组的方法称为平方根法对称正定矩阵A的对角元为正实对称矩阵A正定的充要条件是A的所有特征值为正对称正定矩阵非奇异,其逆亦为对称正定矩阵实对称矩阵A正定的充要条件是A的所有顺序主子式为正正定矩阵的顺序主子阵是正…

正定与半正定矩阵,判别的方法不能混用,否则出错

坑:特征值有0可以知道该矩阵不可能正定,那可以用顺序主子式判断是否为半正定吗? 答案:不能 例子:A,特征值为一个0,两个正数>那就是半正定啦呀 但是,主子式二阶小于0那就不正定了呀两种方法…

线性代数【11】二次型

前言: 矩阵表达的是线性关系的方程组,但是,客官世界,是包括稍微复杂的,二次方程。 尤其几何中,有二次曲线,二次型,就是一个多元函数,是多个变量的二次,齐次…

Lyapunov稳定性分析1(正定函数、二次型正定判定)

一、 正定函数 1.1 定义: 令V(x)是向量x的标量函数,S是x空间包含原点的封闭有限区域。如果对于S中的所有x,都有: 则V(x)是正定的(半正定)。正定函数更直观的描述如下图所示: 如果条件(3&a…