KMP算法是一种改进的字符串匹配算法,KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度
O(m+n)
。
KMP算法的匹配过程:
KMP算法是怎样减少模式串与主串的匹配次数呢???
每当匹配过程出现字符比较不等时
- 主串的
i 指针不动
- 模式串的
j
指针定位
到某个数
上面提到的模式串中 j 指针定位到某个数其实就是next值
若令 next[j]=k,则next[j] 表明当模式中第 j 个字符与主串中相应字符“失配”时,在模式中需要重新和主串中该字符进行比较的字符的位置。
我们规定任何一个串,next[1]=0,举个例子求next:
已知模式串为ABABABB(如下图),在 j =5时,模式串与主串对应字符不匹配,那么求next值就需要找 j 前面的 j-1(即为4) 个字符。j 要移动的下一个位置需要满足这样的性质:最前面的k(即为2)个字符和 j 之前的最后k(即为2)个字符是一样的
,且 k 必须是最大
的情况。
此时FL=“AB”=FR,想要知道下一次的 j 指针对应的值只需要将 FL 与 FR 相重合(通过移动重合)即可 ,重合后此时 j 指向的值为第三个字符(A),说明next值为3。
用公式验证一下,next=FL串长+1=FR串长+1=3
通过上面的例子再来理解一下模式串next函数的定义:
next[j] = 0的意思是主串的第 i 个字符与模式的第一个字符不等,应从主串的第 i+1 个字符起重新进行匹配
由此上面的定义我们可以推出模式串的next函数值,举个例子:
如果按照上面的next值进行匹配,就是下面的匹配过程:
KSP算法如下:
int Index_KMP(SString S,SString T,int pos)
{
i=pos;j=1;
while(i<=S.length && j<=T.length) //两个串均未比较到串尾
{
if(j==0 || S.ch[i]==T.ch[j])
{
++i;++j;} //继续比较后续字符
else
j=next[j]; //模式串向右移动
}
if(j>T.length) return i-T.length; //匹配成功
else return 0; //匹配失败
}
计算next函数值(
O(m)
)算法如下:
void get_next(SString T,int next[])
{
i=1;next[1]=0;j=0;
while(i<T.length)
{
if(j==0 || T