字符串匹配的KMP算法

经典字符串匹配算法——KMP算法 KMP算法 KMP算法是一种高效的字符串匹配算法,在传统暴力遍历匹配的基础上做了一定的优化。 首先KMP算法的实现也是使用了回退思想,不过与暴力遍历不同,KMP的回退,是让子串进行匹配,而不是主串。 KMP示例 首先我们来看两个例子来理解KMP算法: 例1: 分别从str的i和sub的j位置处开始匹配: 此时a与c不匹配,如果暴力遍历的话,是i回到到b,j也回到a,重新一轮匹配。而KMP算法,是将子串的j回到第二个a,str[i]与sub[j]重新开始匹配。原因很明显,第二个ab与第一个ab是相同的,因 阅读详情

原文链接:http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

作者: 阮一峰

日期: 2013年5月 1日

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

举例来说,有一个字符串"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"的位置。

(完)

字符串模式匹配算法——KMP算法 字符串是一种常见的数据结构,它由一个字符序列组成,可以被视为字符的数组或列表。每个字符都有一个对应的索引位置,允许对字符串进行访问、修改和操作。对于字符串而言,寻找字符串中子串的位置是最重要的操作之一,查找子串位置的操作通常称为。 阅读详情

相关推荐

字符串匹配算法--朴素匹配KMP算法

字符串匹配:是输入源串与子串,在源串中寻找子串,并在源串中返回子串在源串中第一次出现的位置。 对此问题,我们提供两种方法:朴素匹配KMP算法。我们假设源串长度为n,子串长度为m 朴素匹配:这个方法也称为暴力匹配,因为他就是我们最容易想到的一种字符串匹配算法。就是从源字符串开始搜索,若出现不能匹配,则从原搜索位置+1进行搜索。 那么它的时间复杂度就需要O(n*m),可以看出时间复杂度很高。...

Eunice_fan1207的博客 1522

ACBM算法

ACBM算法ACBM算法是在AC自动机的基础之上,引入了BM算法的多模扩展,实现的高效的多模匹配。和AC自动机不同的是,ACBM算法不需要扫描目标文本串中的每一个字符,可以利用本次匹配不成功的信息,跳过尽可能多的字符,实现高效匹配。   比如:{P} = {her,wh

么刚的专栏 1万+

KMP字符串匹配算法

字符串匹配算法朴素字符串匹配算法Rabin-Karp算法有限自动机KMP算法 朴素字符串匹配算法 Rabin-Karp算法 有限自动机 KMP算法 KMP算法是Knuth,Morris和Pratt三人设计的线性时间字符串匹配算法。不管是网上还是书上介绍的这个算法都很复杂,让人看了头都麻了,但是它的算法思路是很简单的,就是尽可能地利用已知的信息,从而减少尝试匹配的次数。 什么叫尽可能地利用已知的信息呢? 假设我们有字符串T,要在T中匹配字符串P。 假如匹配进行到如下图的过程,从T的第5个字符a开始的后五个字

m0_63989537的博客 1045

字符串匹配——KMP算法

字符串匹配——KMP算法字符串匹配是计算机编程中最常使用到的基础算法之一。字符串匹配相关的算法很多,Knuth-Morris-Pratt(KMP算法是最常用的之一。最近在学习KMP算法,学习了许多相关的博客,记录一下,以备日后不会写了回来看看。 ​ KMP算法有两个要点:1)部分匹配 和next数组的计算;2)利用部分匹配表解决字符串匹配问题。 1、KMP算法原理 (1)原理 ​ 给定两个字符串:文本串S="BBC ABCDAB ABCDABCDABDE"和模式串P="ABCDABD",要求找

哦豁灬 2万+

字符串匹配算法KMP

目录需求基础知识逻辑解析源码实现 需求 先简单描述溪源曾经遇到的需求: 需求一:项目结果文件中实验结论可能会存在未知类型、转换错误、空指针、超过索引长度等等。这里是类比需求,用日常开发中常出现的错误类型作为需求,如果要以上结论则判断这个项目检测失败; 解决方案一: 大家常用的方式可能是if(){continue;} esle if (){continue;} …或者switch-case等; 方案二:可能会使用集合contain()方法; 方案三:依次匹配字符串中字符(暴力匹配); 以上两种方案都能解决;然

增量星球 4787

字符串匹配——KMP算法【C语言】

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n) 一、暴力算法 int BF(char *chang,char *duan) { int c_strlen=strle...

weixin_45423515的博客 7456

字符串匹配算法KMP详解

本人是普通本科院校的一名大二学生,为提高自身能力特地锻炼自己发表一些文章,题解等, 望各位大佬能够对我这个菜鸟所做多多指正,在此谢过各位啦~~~ 文章的开始,我想向KMP算法的三位创始人Knuth,Morris,Pratt致敬,如此思维之精妙,堪称大神。 KMP算法字符串匹配算法中一个很重要的算法KMP算法的作用是在一个字符串中寻找子串的位置,也叫串的模式匹配。如主串s="aaabbaab",子串t(也叫模板串)="aab",要寻找aab在主串中的位置。 字符串匹配的暴力做法就是分别将两个指针i,

qq_51502732的博客 4647

字符串匹配KMP算法

这种类型字符串题目都可以采用暴力解法,套两层for循环也可以实现,但是时间复杂度太大,采用KMP算法之后,时间复杂度更低。所以掌握KMP算法还是有意义的

Hhjhj255的博客 866

KMP 字符串匹配算法

都说KMP算法难,我说KMP算法真不难,不信你点进来看看。

qq_63943454的博客 1055

Java用KMP算法解决字符串匹配问题

14.4 KMP 算法 14.4.1 应用场景-字符串匹配问题 字符串匹配问题: 有一个字符串 str1= “迪丽热巴 迪丽热巴你你好 迪丽迪丽热巴迪丽热巴你好”,和一个子串 str2=“迪丽热巴你好” 现在要判断 str1 是否含有 str2, 如果存在,就返回第一次出现的位置, 如果没有,则返回-1 先看一下暴力匹配法(不是KMP算法,用暴力匹配KMP算法做对比) 如果用暴力匹配的思路,并假设现在 str1 匹配到 i 位置,子串 str2 匹配到 j 位置,则有: 如果当前字符匹配成功(即 s

当一个合格的软件工程师 2738

字符串匹配--KMP算法

KMP算法是一种高效的字符串匹配算法,通过利用已匹配部分的信息避免不必要的回溯。其核心是构建next数组,记录模式串的最长公共前后缀,从而在匹配失败时快速调整模式串位置。相比暴力匹配O(n*m)的时间复杂度,KMP算法优化至O(n+m)。实现包括两部分:1)计算next数组;2)利用next数组进行匹配。虽然原理复杂,但掌握后能显著提升字符串处理效率。学习时建议理解算法逻辑而非死记模板,通过手动演算加深理解。该算法在编程竞赛中应用广泛,值得深入学习。

m0_65384516的博客 753

字符串匹配算法——暴力匹配算法KMP算法

1) KMP 是一个解决模式串在文本串是否出现过,如果出现过,获取最早出现的位置。2) Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP 算法”,常用于在一个文本串 S 内查找一个模式串 P 的出现位置,这个算法由 Donald Knuth、Vaughan Pratt、James H. Morris 三人于 1977 年联合发。3) KMP 算法:利用之前判断过信息,通过一个next 数组。

weixin_43713707的博客 1534

浅谈字符串匹配算法—BF算法KMP算法

字符串匹配,在实际编程中经常遇到。其相应的算法有很多,本文就BF算法KMP算法,谈一下自己的理解。并结合平时编程,修改了一下,使其更符合我们的使用习惯。(注:标准BF算法KMP算法,为研究方便,其字符数组[0]存放的都是字符串的长度。本文讲解中,并没有保存字符串长度。后面给出的示例代码中,字符数组中是否保存有字符串长度,都给出了相应的算法代码。) 一、BF算法(Brute Force):

一个程序猿的故事 8273

字符串匹配算法KMP

问题: 给你两个字符串 s和 pat ,请你在 s 字符串中找出 pat 字符串出现的第一个位置(下标从 0 开始),如果不存在则返回-1。 1.暴力匹配算法。 暴力匹配算法较好理解,其大致原理如图: 当D和E不匹配的时候,pat模式串会向右移动一位,然后继续匹配。 一直这样匹配,直到匹配到模式串或者匹配不成功为止。 代码如下: class Solution { public stat...

m0_61799623的博客 2793

算法字符串匹配KMP算法

对于字符串匹配,暴力法是对每个位置进行逐位匹配,只要有匹配失败的,就从待匹配串的下个位置开始从头匹配,这样的时间复杂度是O(MN)。 KMP算法能解决这样效率低下匹配,其核心思想是保留已匹配的前缀和,避免重复匹配,时间复杂度是O(M+N)。 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"? 首先,字符串"BBC ABCDAB ABCDABCDABDE"的第一个字符与搜索词"ABCDABD"的第一个字符,进行比较。因为B与A

Steven_L_的博客 2648

字符串匹配——KMP算法讲解

KMP算法讲解

Dirty_artist的博客 1003

字符串匹配KMP算法

新年第一篇博客也是第一次写关于算法的博客。这两天帮同学看《算法与数据结构》试题,其中涉及到字符串匹配KMP算法,借机重新温习整理了一下,也算有了新的体会与感悟,希望能够讲得清楚。 从字符串匹配讲起 我们都说KMP算法是一种高效的字符串匹配算法,所以首先先定义下字符串匹配问题:给定一个文本串T(也叫主串S),和一个模式串P,现在要找出S中与P匹配的子串,如果存在就返回匹配位置,否则返回-1。 暴力...

zxhohai的博客 1541

KMP算法字符串匹配

KMP算法字符串匹配

qq_47898999的博客 1556
上一篇: Topcoder SRM565 DIV2 500分-c++
ymwtz
博客等级 码龄13年 1粉丝 11原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值