一、KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。
二、KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。
三、KMP算法的时间复杂度为O(m+n)。
通过对模式串进行操作,得到next数组,这里传入的参数为模式串
//得到next数组
void getNext(Str str, int next[])
{
int i = 0, j = -1;
next[i] = j;
while(i < str.length-1)
{
if(j < 0 || str.ch[i] == str.ch[j])
{
++i;
++j;
next[i] = j;
}
else
{
j = next[j];
}
}
}
KMP算法的实现
//kmp算法
int KMP(Str str, Str &substr, int next[])
{
int i = 0, j = 0; //i指向 str 串;j指向 substr 模式串
while(i < str.length && j < substr.length)
{
if(str.ch[i] == substr.ch[j] || j < 0)
{
++i;
++j;
}
else
{
j = next[j];
}
}
if(j >= substr.length)
return i - substr.length;
else
return 0;
}
KMP算法中的i不需要回溯:意味着对于规模较大的外存中的字符串的匹配操作可以分段进行,先读入内存一部分进行匹配,完成之后即可写回外存,确保在发生不匹配时不需要将之前写回外存的部分再次读入,减少了I/O操作,提高了效率。
四、KMP算法的改进:
对next数组的改进:nextval数组
从next数组得到nextval数组:设模式串为str
1、nextval[0]=-1;
2、如果str.ch[ j ] == str.ch[ next[ j ] ],则nextval[ j ] = nextval [ next[ j ] ];
3、如果str.ch[ j ] != str.ch[ next[ j ] ],则nextval[ j ] = j;
极端案例:substr:AAAAAB
//得到nextval数组
void getNextval(Str str, int nextval[])
{
int i = 0, j = -1;
nextval[i] = j;
while(i < str.length-1)
{
if(j < 0 || str.ch[i] == str.ch[j])
{
++i;
++j;
if(str.ch[i] == str.ch[j])
{
nextval[i] = nextval[j];
}
else
{
nextval[i] = j;
}
}
else
{
j = nextval[j];
}
}
}