KMP算法的原则:每当匹配不相等时,主串中i指针不变,模式串中j指针移动到恰当的位置。
本博客仍旧采用如下定长顺序存储,数组的0号单元用于存放字符串长度。
#define MAXSTRLEN 255//宏定义串的最大长度MAXSTRLEN为255
typedef unsigned char SString[MAXSTRLEN + 1];//定义SString为无符号字符数组类型,数组长度为256
#KMP算法解析
1.用Si表示主串中第i个字符,用Pj表示模式串中第j个字符;
当Si与Pj匹配不相等时,i不变,j变为k。
(i不变对应了主串中i指针不回溯的原则,j变为k对应了next函数,即k=next[j])
2.若要让Si与Pk继续匹配,必须满足的条件是P1....Pk-1与Si-k+1....Si-1匹配相等
3.已知P1....Pj-1与Si-j+1....Si-1匹配相等,可推出Pj-k+1....Pj-1与Si-k+1....Si-1匹配相等
4.所以若要让Si与Pk继续匹配,必须满足P1....Pk-1=Pj-k+1....Pj-1
*即必须满足前k-1个字符与后k-1个字符相等
5.又因为k越大,节省的比较次数就越多,所以选择满足条件*的最大k值
**补充说明:当j=1时,Si与Pj就不匹配时,规定k=0
#演示手工计算next值
j 1 2 3 4 5 6 7 8
模式串 a b a a b c a c
next[j]
当j=1时,根据定义k=0;
当j=2时,利用条件*,观察字符串a,可知k-1=0,k=1;
当j=3时,利用条件*,观察字符串ab,可知k-1=0,k=1;
当j=4时,利用条件*,观察字符串aba,可知k-1=1,k=2;
当j=5时,利用条件*,观察字符串abaa,可知k-1=1,k=2;
当j=6时,利用条件*,观察字符串abaab,可知k-1=2,k=3;
当j=7时,利用条件*,观察字符串abaabc,可知k-1=0,k=1;
当j=8时,利用条件*,观察字符串abaabca,可知k-1=1,k=2.
next[j]:1122312
#由此KMP算法可以由暴力匹配算法改进而得出
int Index_KMP(SSTring S,SSTring T,int pos)//利用KMP算法求模式串T在主串S中第pos个字符之后的第一个出现位置
{
int i=pos;
int j=1;
while(i<=S[0]&&j<=T[0])
{
if(j==0||S[i]==T[j])//加上j==0,巧妙解决了Si与P1不匹配时的情况,使得Si+1与P1继续比较
{
i++;
j++;
}
else
j=next[j];//运用了KMP算法核心原则,当Si与Tj不等时,i不变,j变为k(即next[j])
}
if(j>T[0]) return i-T[0];
else return 0;
}
#get_next函数解析
1.由定义得,next[1]=0;
2.设next[j]=k
根据条件*可知P1....Pk-1=Pj-k+1....Pj-1;
若Pk=Pj,则由P1....Pk=Pj-k+1....Pj,得出next[j+1]=k+1,即next[j+1]=next[j]+1;
3.若Pk不等于Pj时,仿照KMP算法,将整个模式串既看成主串又看成模式串
Pj-k+1=P1
Pj-k+2=P2
...
Pj-1=Pk-1
当Pj不等于Pk时,j不变,k变为next[k](设k1=next[k]);
若Pj=Pk1,则根据条件*可推出P1....Pk1=Pj-k1+1....Pj;
next[j+1]=k1+1;
若Pj不等于Pk1,可继续按此方法推下去,求出Kn.
4.若没有满足条件*与Pj=Pkn的Kn,则next[j+1]=1.
void get_next(SSTring T,int next[])
{
next[1]=0;//由定义得到的前提条件
int j=1;
int k=0;//根据假设next[j]=k设置j,k初值
while(j
#本博客参考了《数据结构(C语言版)》(严蔚敏,吴伟民编著)