前言:本文是对数据结构(C语言版)作者:严蔚敏版的kmp粗略解释,只是基于作者目前的理解写下,了解不够精深,文笔不好请多多见谅,如果有不了解或者写错的地方欢迎大家给我留言或者私信给我。
KMP算法原理:
百度上对KMPlayer算法的解释。
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。
首先看书上关于kmp的程序代码。
int Index_KMP(SString S,SString T,int pos){
//利用模式串T对的next函数求T在主串S中的第pos个字符之后的位置
//其中,T非空 1<= pos<=S的长度
int i=pos,j=1;,
while(i<=S[0]&&j<=T[0]){
if(j==0||S[i]==T[j]){ ++i;++j; }
else j=next[j];
}
if(j>T[0]) return i-T[0]; //
else return 0;
}
观察代码可以发现i的值没有发生改变,这也就意味着主串中的匹配值(即匹配字符)不动,并且该匹配值为之前主串和模式串匹配中匹配不对的字符,而真正移动的是模式串,模式串依据next[j]来决定他移动的位置。这样描述可能有点难以理解,简单的来说,kmp算法精髓是当发生不匹配的现象后,会通过我们所求的next来判断模式串之前与主串匹配李有没有可以减少的无用匹配,直接跳到有用匹配上。
这样就引出什么样的匹配才是真正有用的匹配,这需要我们从next的取值中分析:
next
0 1 2 3 4 5 6 7 8 9 10 11 模板下标 q
A B C D A B D A B C D A 字符串模板P
0 0 0 0 1 2 0 1 2 3 4 5 next 记录
next[j]取值:前缀(必须包括第一个字符)与后缀(必须包括最后一个字符)看是否匹配,匹配则next[j]=匹配数+1;不匹配则next[j]=0+1;(匹配的时候不包括在j位置上的字符)。
所以我们可以发现有用的匹配是在主串匹配错误的字符与模式串相同字符中对应的前提下,看主串之前的字符串是否与模式串中对应的字符之前的字符串是否匹配。
void get_next(SString T,int next[]){
//求模式串T的next函数值并存入数组next;
int i=1,j=0;
next[1]=0;
while(i<T[0]){
if(j==0||T[i]==T[j]){ ++i;++j;next[i]=j; }
else j=next[j];
}
}
求next[j]数组的过程同时也是在求匹配的过程,将前缀作为目标串,而主串作为匹配串
并且是从最后一个字符开始。并且next[j]是有规律的,他的增长是逐渐增长,从1到2到3开始增长。
以上是我对KMP算法的初略了解,出现错误请多多关照,欢迎大家指正,这个是博主觉得比较好的对kmp介绍,大家可以参考参考