Knuth-Morris-Pratt算法(简称KMP)是最常用字符传匹配算法之一。它以三个发明者命名,起头的那个K就是著名科学家Donald Knuth。KMP算法对于任何模式和目标序列,都可以在线性时间内完成匹配查找,而不会发生退化。
1、KMP算法的原理
KMP算法中主要的概念是next数组,有的叫失配函数,用来计算子串与母串匹配失败时子串移动的位数。KMP算法就是利用next数组来提高效率,不用每次匹配失败时一位一位地往下移。
字符串匹配的一般步骤
KMP算法中的匹配步骤
next数组的含义
公共最长部分:前缀后缀相同的最大长度
2、匹配失败时,子串指针移动到最大长度+1位置原因,怎么保证了不会遗漏
3、next数组构造代码的理解
next[0]=-1;
k=-1;
j=0;
if(k==-1||T[k]==T[j])
{
next[++j]=++k;
}
else
{
k=next[k];
}
k表示前缀指针,j表示后缀指针。next[j]的求解首先在next[j-1]的基础上处理,因为next[j]的最大值只能比next[j-1]大1。假设可能大2,可以推出j-1的next值可以取到next[j-1]+1,大于next[j-1],产生矛盾。
如果前缀和后缀新加的一个字符是相等的,next[j]等于next[j-1]加1。
如果不相等,k指针跳到next[k],这一步是用来找此时可能存在的最大公共最长部分即next[k]+1。首先跳到next[k]可以保证不会存在更大的公共最长部分,因为如果为next[k]+2,则k指针位置的next值可以取到next[k]+1,产生矛盾。其次跳到next[k]的位置和KMP算法匹配失败跳转位置选择的原理类似,可以减少计算量。
4、KMP算法的优化
KMP算法的原理是匹配失败时,母串指针i不变,子串指针由j跳转到next[j]的位置。匹配失败时是S[i]与T[j]比较,而如果T[next[j]]与T[j]相同,则跳转前后的比较情况是一样的都不相等,还需要在再跳转一次。故可以给next数组进行优化,如果T[next[j]]与T[j]相同,next[j]的取值为next[next[j]],即next[k]。
if(k==-1||T[k]==T[j])
{
next[++j]=++k;
if(T[j]==T[k])
{
next[j]=next[k];
}
}