从零理解的KMP算法

KMP算法的优势

KMP算法是一个效率很高的字符串匹配算法,算法大意是:给定两个字符串y,x,判断x是否在y出现过。如果暴力搜索的话复杂度为O(lenx*leny),但用KMP算法解决的话,

我们只需要一个O(lenx)的预处理,优化暴力的复杂度变成O(lenx+leny),这里lenx,leny都代表字符串的长度。

KMP算法的匹配方法

给定一个y为:ababacddsdfwwrababsababa

给定一个x为:ababa

我们先用暴力的方法跑一遍

1.

ababacddsdfwwrababsababa

ababa

这里我们可以看到指针到了第一个字符时候,x和y在此指针上的字符相同;

2.

ababacddsdfwwrababsababa

ababa

继续让指针向后,我们发现此时x和y的字符仍相同,那么继续

当我们跑下去会发现第一个y中含有x的字符串,继续往下跑时会发现第一个字符就不相同,那就继续往下,直到找到第一个相同的字符

3.

ababacddsdfwwrababsababa

ababa

这个时候我们重复第一步,发现找到了最后一个c和b不相同,那么我们就会放弃这次查找,又从头开始匹配;

4.

ababacddsdfwwrababsababa

ababa

显然这样效率太低了,那有没有办法提高效率呢???

答案当然是有的,我们可以发现在第三步的时候x的aba与y的aba是相同的,如果这一段两个字符串没法匹配,说明y中的aba一段一定不可以再匹配了,我们就可以跳过aba直接进行下一段搜索如下图

ababacddsdfwwrababsababa

ababa

接下来如何判断就是KMP干的事情了

我们可以想到如果计算出来x字符串的一个转移函数next就会轻松很多。

next数组的含义就是一个字符串的其中一个字符之前的最长前缀和最长后缀相同的长度。

举个例子

abababa  最长前缀和最长后缀都是aba

abebc       就没有最长前缀和最长后缀

qqqq       最长前缀和最长后缀就是qqq(注意不是qqq

那么对于咱们的字符串ababa我们就可以做出处理

分别计算与a,ab,aba,abab,ababa的长度相同的最长前缀和最长后缀长度(如果下面不理解就仔细看上面的例子。

next[0]=-1,next[1]=-1,next[2]=0,next[3]=1,next[4]=2

-1表示不存在,0表示长度为1,1表示长度为2,以此类推(继续看就会知道为什么这么存

那么根据我上面说的要想把那些多余的搜索跳过就要使用这个数组,

想必大家都已经明白了

当我们搜到一个字符匹配,此时它对应的next有一个值,当他下一个字符不匹配时,可以直接移动next的值+1个长度,继续比较。

ababacddsdfwwrababsababa

ababa

ababacddsdfwwrababsababa

ababa

洛谷上题号P3375是这道题的模板,大家可以去练习一下

时间: 2024-10-24 08:48:46

从零理解的KMP算法的相关文章

KMP算法,这是我看到的最简单的最好理解的KMP算法

看的文章来源于 http://www.cnblogs.com/c-cloud/p/3224788.html 好理解在求Next的方法(推荐看原文) Next实现 1 void makeNext(const char P[],int next[]) 2 { 3 int q,k;//q:模版字符串下标:k:最大前后缀长度 4 int m = strlen(P);//模版字符串长度 5 next[0] = 0;//模版字符串的第一个字符的最大前后缀长度为0 6 for (q = 1,k = 0; q

KMP算法的理解

---恢复内容开始--- 在看数据结构的串的讲解的时候,讲到了KMP算法——一个经典的字符串匹配的算法,具体背景自行百度之,是一个很牛的图灵奖得主和他的学生提出的. 一开始看算法的时候很困惑,但是算法思想很简单,就是在暴力匹配的基础上得出的. 暴力匹配 这里有必要说一下暴力匹配,暴力匹配更简单,就是按照人的常规思维去匹配字符串,拿模式串(P)的第一个字符去和给定串(S)比较,S从左往右看,一看,第一个,呀~不对,啥也不说了,第一个都不对了,后边还比个毛.所以,这一次比较,S中第一个字符开头是匹配

KMP算法——从入门到懵逼到了解

本博文参考http://blog.csdn.net/v_july_v/article/details/7041827 关于其他字符串匹配算法见http://blog.csdn.net/WINCOL/article/details/4795369 暴力匹配算法 暴力匹配的思路,假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置,则有: 如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符: 如果失配(即S[i]! = P[j]),令i = i - (j

KMP算法学习(详解)

kmp算法又称“看毛片”算法,是一个效率非常高的字符串匹配算法.不过由于其难以理解,所以在很长的一段时间内一直没有搞懂.虽然网上有很多资料,但是鲜见好的博客能简单明了地将其讲清楚.在此,综合网上比较好的几个博客(参见最后),尽自己的努力争取将kmp算法思想和实现讲清楚. kmp算法完成的任务是:给定两个字符串O和f,长度分别为n和m,判断f是否在O中出现,如果出现则返回出现的位置.常规方法是遍历a的每一个位置,然后从该位置开始和b进行匹配,但是这种方法的复杂度是O(nm).kmp算法通过一个O(

KMP算法 - 字符串匹配的简单运用 --- HDU 1711

Number Sequence Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11606    Accepted Submission(s): 5294 Problem Description Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b

【详解】KMP算法

前言 KMP算法是学习数据结构 中的一大难点,不是说它有多难,而是它这个东西真的很难理解(反正我是这么感觉的,这两天我一直在研究KMP算法,总算感觉比较理解了这套算法, 在这里我将自己的思路分享给大家,也是检验一下自己有没有真正掌握这个算法,错误的地方也请大家指正.嘤嘤嘤~~~ 注:可供参考的资料有很多,视频的话个人推荐B站的UP主正月点灯笼,博客的话有很多,不过不要贪多,不然容易混乱,不同的人对这个算法也是有不同的理解的! 背景 了解一个算法你要明白它的出处,KMP算法是由三位大牛同时研究出来

深入理解KMP算法

首先从直观上看KMP存在的价值: 一般在遇到字符串匹配的问题的时候,一种朴素的比较方式就是 int BFMatch(char *s,char *p) { int i,j; i=0; while(i<strlen(s)) { j=0; while(s[i]==p[j]&&j<strlen(p)) { i++; j++; } if(j==strlen(p)) return i-strlen(p); i=i-j+1; //指针i回溯 } return -1; } S:  ababca

KMP算法 --- 深入理解next数组

KMP算法的前缀next数组最通俗的解释 我们在一个母字符串中查找一个子字符串有很多方法.KMP是一种最常见的改进算法,它可以在匹配过程中失配的情况下,有效地多往后面跳几个字符,加快匹配速度. 当然我们可以看到这个算法针对的是子串有对称属性,如果有对称属性,那么就需要向前查找是否有可以再次匹配的内容. 在KMP算法中有个数组,叫做前缀数组,也有的叫next数组,每一个子串有一个固定的next数组,它记录着字符串匹配过程中失配情况下可以向前多跳几个字符,当然它描述的也是子串的对称程度,程度越高,值

KMP算法详解 --- 彻头彻尾理解KMP算法

[经典算法]——KMP,深入讲解next数组的求解 前言 之前对kmp算法虽然了解它的原理,即求出P0···Pi的最大相同前后缀长度k:但是问题在于如何求出这个最大前后缀长度呢?我觉得网上很多帖子都说的不是很清楚,总感觉没有把那层纸戳破,后来翻看算法导论,32章 字符串匹配虽然讲到了对前后缀计算的正确性,但是大量的推理证明不大好理解,没有与程序结合起来讲.今天我在这里讲一讲我的一些理解,希望大家多多指教,如果有不清楚的或错误的请给我留言. 1.kmp算法的原理: 本部分内容转自:http://w