【模式匹配】KMP算法的简明理解
2014-04-08 09:55
169 查看
KMP算法是模式匹配算法的一种改进算法。这种算法是D.EKunth与V.P.Pratt和J.H.Morris同时发现的,因此称为克鲁特——莫里斯——普拉特操作,简称为KMP算法。
假设给定子串P,待查找的字符串T.
这个算法是目的是在子串中找出待查找的的字符串,要求从子串P中超出所有与字符串T相同的子串,这称为模式匹配。(返回结果可以是子串在P中的位置)
首先给出一个例子:
从t0开始,使得P的连续m个字符和T相同。
一、解决模式匹配的方案:
1、 普通的模式匹配算法:将T中的字符串和P一一比较,如果遇到不相同的字符,则将T右移一位将继续上面的操作,直到匹配成功或者匹配到最后一位为止。
举例:
从上面的例子可以看出在最坏的情况下每次都要比较m次,比较的趟数为n+1-m趟,所以总的比较次数为m*(n-1+m)。
2、 KMP算法:从上面普通匹配算法来看,其实有很多比较是可以避免的,因为上面的过程出现的回溯。那么KMP将会尽量避免回溯产生的冗余比较。
KMP算法主要是要确认以下问题:
A、字符串不等时,T向右移动多少个位置;
B、移动后从T的第几个字符开始和P中的那个字符比较;
KMP的关键是借助了一个和T字符串长度相等的数组next,这组数组只与T自身有关(与P无关)。现在给出next的定义:每个T的字符对应一个next直接给出一个相关的式子。
① 字符串不等时,T向右移动i-next[i] (注意i可以取到0)个位置;
② 移动后从T的第next[i] (当为-1时,取值为0)个字符开始和P中的那个字符比较;
以下是计算next的方法(i是从0开始的)
-1(i=0)
next[i]={ Max{k|0<k<j-1,”t0…t(k-1)”=”t(i-k)…t(i-1)”}
0(其他情况)
上述情况二中其实是计算第i个字符比较不同时,从T的i-1序号向前推进能和t0开始的最多k个字符相等,取值那个最大的k即可。
例如下面的例子:
假设给定子串P,待查找的字符串T.
这个算法是目的是在子串中找出待查找的的字符串,要求从子串P中超出所有与字符串T相同的子串,这称为模式匹配。(返回结果可以是子串在P中的位置)
首先给出一个例子:
P: | p0 | p1 | p2 | p3 | p4 | p5 | …… | pm-1 | …… | pn |
T: | t0 | t1 | t2 | t3 | t4 | t5 | …… | tm-1 |
一、解决模式匹配的方案:
1、 普通的模式匹配算法:将T中的字符串和P一一比较,如果遇到不相同的字符,则将T右移一位将继续上面的操作,直到匹配成功或者匹配到最后一位为止。
举例:
P: | a | a | a | a | a | a | a | a | a | b |
T: | a | a | a | b |
2、 KMP算法:从上面普通匹配算法来看,其实有很多比较是可以避免的,因为上面的过程出现的回溯。那么KMP将会尽量避免回溯产生的冗余比较。
KMP算法主要是要确认以下问题:
A、字符串不等时,T向右移动多少个位置;
B、移动后从T的第几个字符开始和P中的那个字符比较;
KMP的关键是借助了一个和T字符串长度相等的数组next,这组数组只与T自身有关(与P无关)。现在给出next的定义:每个T的字符对应一个next直接给出一个相关的式子。
① 字符串不等时,T向右移动i-next[i] (注意i可以取到0)个位置;
② 移动后从T的第next[i] (当为-1时,取值为0)个字符开始和P中的那个字符比较;
以下是计算next的方法(i是从0开始的)
-1(i=0)
next[i]={ Max{k|0<k<j-1,”t0…t(k-1)”=”t(i-k)…t(i-1)”}
0(其他情况)
上述情况二中其实是计算第i个字符比较不同时,从T的i-1序号向前推进能和t0开始的最多k个字符相等,取值那个最大的k即可。
例如下面的例子:
P: | a | c | a | b | a | a | b | a | …… |
T: | a | b | a | a | b | c |
i | 0 | 1 | 2 | 3 | 4 | 5 | |||
T: | a | b | a | a | b | c | |||
next[i] | -1 | 0 | 0 | 1 | 1 | 2 |
#include<stdlib.h> #include<iostream> using namespace std; void getnext(char* t,int next[]){ int i=-1,j=0,n=strlen(t); next[0]=-1; while(j<n-1) { if(i==-1||t[i]==t[j]){ i++; j++; next[j]=i; } else i=next[i]; } } int KMP(char* s,char* t,int next[],int pos) { int i=pos,j=0,len1=strlen(s),len2=strlen(t); while((i<len1)&&(j<len2)) { if(j==-1||s[i]==t[j]) {j++;i++;} else j=next[j]; } if(j==len2) return i-len2; else return -1; } int index_KMP(char* s,char* t,int next[],int pos) { int i=0,j=0,len1=strlen(s),len2=strlen(t),re=0; while(i<len1&&j<len2) { if((j==-1)||(s[i]==t[j])) {i++;j++; } else j=next[j]; re=max(re,j); } return re; } int main() { char ax[]="abaabcacacabaabaabcacaabc"; char ah[]="abaabcac"; int next[8]={0}; int pos=0,startpos=0,endpos; while(pos!=-1){ getnext(ah,next); pos=KMP(ax,ah,next,startpos); endpos=index_KMP(ax,ah,next,startpos); cout<<"pos="<<pos<<",endpos="<<endpos<<endl; startpos=pos+endpos; } return 0; }
相关文章推荐
- 模式匹配之KMP算法的理解(一)
- 模式匹配之KMP算法的理解(二)
- 《数据结构》之串的模式匹配算法——KMP算法
- 字符串模式匹配KMP算法
- 数据结构20:KMP算法(快速模式匹配算法)详解
- 改进的模式匹配算法——KMP算法
- 改进的模式匹配算法——KMP算法
- 字符串模式匹配KMP算法
- java 中模式匹配算法-KMP算法实例详解
- Java数据结构之字符串模式匹配算法---KMP算法
- 字符串模式匹配算法--BF & KMP算法
- KMP算法字符串模式匹配
- 转一篇写的比较好的文章-----模式匹配的KMP算法详解
- KMP算法实现字符串的模式匹配完整C代码
- 查表:字符串模式匹配(BF、KMP算法)
- 大话数据结构十一:字符串的模式匹配(KMP算法)
- 字符串模式匹配————BF、KMP算法基础详解
- 串的模式匹配算法:BF和 KMP算法
- 模式串的快速匹配算法,kmp算法,尊重前人成果,创造新未来
- 改进的模式匹配算法——KMP算法