【数据结构和算法】:KMP模式匹配算法

Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个文本串S内查找一个模式串P 的出现位置,这个算法由Donald Knuth、Vaughan Pratt、James H. Morris三人于1977年联合发表,故取这3人的姓氏命名此算法。整个KMP的重点就在于当某一个字符与主串不匹配时,我们应该知道j指针要移动到哪里。

如图:C和D不匹配了,我们要把j移动到哪?显然是第1位,因为如下面蓝框所示,前面A已经匹配。

下面也如此:

可以把j指针移动到第2位,因为前面有两个字母是一样的

至此我们得知,当匹配失败时,j要移动的下一个位置k。存在着这样的性质:最前面的k个字符和j之前的最后k个字符是一样的。

用数学公式表示如下:

P[0 ~ k-1] == P[j-k ~ j-1]

可以通过递推求得next 数组,代码如下所示:

01 void Next(char* p,int next[])

02 {

03     int pLen=strlen(p);

04     next[0]=-1;

05     int k=-1;

06     int j=0;

07     while (j<pLen-1)

08     {

09         //p[k]表示前缀,p[j]表示后缀

10         if (k==-1 ||
p[j]== p[k])

11         {

12             ++k;

13             ++j;

14             next[j]=k;

15         }

16         else

17         {

18             k=next[k];

19         }

20     }

21 }

next[j]的值(也就是k)表示,当P[j] != T[i]时,j指针的下一步移动位置。

当j为0时,如果这时候不匹配,j已经在最左边了,不可能再移动了,这时候要应该是i指针后移。所以在代码中才会有next[0] = -1;这个初始化。

P[k] != P[j]

从代码上看应该是这一句:k = next[k];为什么是这样子?你看下面应该就明白了。

有了next数组之后就一切好办了,我们可以写KMP算法了:

01 int KmpMatch(char*
s,char* p)

02 {

03     int i=0;

04     int j=0;

05     int sLen=strlen(s);

06     int pLen=strlen(p);

07     while (i<sLen&&j<
pLen)

08     {

09         //①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++      

10         if (j==-1
|| s[i]== p[j])

11         {

12             i++;

13             j++;

14         }

15         else

16         {

17             //②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]      

18             //next[j]即为j所对应的next值        

19             j=next[j];

20         }

21     }

22     if (j==pLen)

23         return i-j;

24     else

25         return -1;

26 }

备注:KMP算法是经典算法,原理和一些框图参考了网上的技术博客,这里融入自己的一些理解记录,以加深自己对算法的理解,同时与广大网友交流,欢迎批评指正!

时间: 2024-11-08 14:51:02

【数据结构和算法】:KMP模式匹配算法的相关文章

数据结构--KMP模式匹配算法

今天,在看数据结构--串这一章节时,看到了KMP算法,相对较复杂些,在此单独做下整理. kmp算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特--莫里斯--普拉特操作(简称KMP算法).KMP算法的关键是根据给定的模式串W1,m,定义一个next函数.next函数包含了模式串本身局部匹配的信息. 例子: 假如我们要比较两个字符串是否相等. 在T串中查找S串.我们用最笨的方法去想,就是将T串与S串中的每一个元素一一去匹配,

Java数据结构-串及其应用-KMP模式匹配算法

串(string)是由零个或多个宇符组成的有限序列,又名叫字符串. 定义的解释: ??串中的字符数目n称为串的长度,定义中谈到"有限"是指长度n是一个有限的数值. ??零个字符的串称为空串(null string),它的长度为零,可以直接用两双引号一表示,也可以用希腊Φ字母来表示. ??所谓的序列,说明串的相邻字符之间具有前驱和后继的关系. 下面是串的一些概念性东西: ??空格串,是只包含空格的串.注意它与空串的区别,空格串是有内容有长度的,而且可以不止一个空格. ??子串与主串,串中

详细解读KMP模式匹配算法

转载请注明出处:http://blog.csdn.net/fightlei/article/details/52712461 首先我们需要了解什么是模式匹配? 子串定位运算又称为模式匹配(Pattern Matching)或串匹配(String Matching).在串匹配中,一般将主串称为目标串,将子串称为模式串.本篇博客统一用S表示目标串,T表示模式串,将从目标串S中查找模式串T的过程称为模式匹配. 虽然我们的主角是KMP模式匹配算法,但我们还是要先从暴力匹配算法讲起,通过发现暴力匹配算法存

朴素和KMP模式匹配算法(Java)

朴素模式匹配算法 public class Test { //朴素模式匹配算法 public int Index(String s,String t,int pos){ int i = pos;//主串中第几个位置开始比较 int j = 0;//模式串中的第一个位置 while(i<s.length()&&j<t.length()){ if(s.charAt(i)==t.charAt(j)){ i++; j++; }else { i = i-j+1;//主串的下一个位置 j

改进版KMP模式匹配算法

背景 朴素匹配算法太低效了.冗余过多,已经比较过的,没必要重复:可以从比较结果中推导出来的,也没必要再重复. 核心 主串不回溯,变化要匹配的串的下一次比较的位置. 实现 两个函数,一个提供next数组,即存储要匹配的串的每一个元素匹配失败后,下一次要比较的位置的数组.另一个实现匹配. java代码 public class KMP {//获取next数组private int[] getNext(char[] t_char){int size = t_char.length;int next[]

串-KMP模式匹配算法(nextval数组)

#include <stdio.h> #include <stdlib.h> #include <string.h> void get_next(char T[100],int *next); int Index_KMP(char S[100],char T[100],int pos); int main() { int n; char S[100],T[100]; gets(S); gets(T); n=Index_KMP(S,T,2); printf("%

数据结构(三)串---KMP模式匹配算法之获取next数组

(一)获取模式串T的next数组值 1.回顾 我们所知道的KMP算法next数组的作用 next[j]表示当前模式串T的j下标对目标串S的i值失配时,我们应该使用模式串的下标为next[j]接着去和目标串失配的i值进行匹配 而KMP算法的next求值函数 我们可以知道next除了j=1时,next[1]为0,其他情况都是比较前缀和后缀串的相似度(第三种情况是当相似度为0时,next值为0+1=1) next数组,是用来评判前后缀的相识度,而next值,则是等于相似度加一 2.思考 虽然我们知道是

数据结构(三)串---KMP模式匹配算法实现及优化

KMP算法实现 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define MAXSIZE 40 typedef int ElemType; typedef int Status; //设置串的存储结构 typede

改进KMP模式匹配算法

看了算法的大致步骤,然后自己一一证明了每一步的正确性,注释里写了一些理解. 这也不是新鲜的做法,只是感觉这个程序非常精巧,反复地使用数学归纳法. 让我感觉很新鲜. 1 /* 2 next[i]存放:match[i]处失配,orig在对应位置将要匹配的值 3 按照KMP的思想, 4 即是1到i-1子串中最长相同前后缀的前缀最后一项的后一项 5 且这一项和match[i]不同 6 7 若不存在同缀子串但是第一项与i项不同,值为1. 8 若不存在同缀子串且第一项与i项相同,值为0,即将j向后移动一个位