什么是KMP算法?

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,简称KMP算法。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。

KMP算法与BF(暴力**法)的区别

KMP算法是建立在BF算法基础上的,KMP算法与BF算法的最大区别在于,BF算法只能一位一位匹配,而KMP算法能够实现省去不必要的匹配步骤,从而实现跳位的匹配(具体如何跳位,看下图演示)。
模式匹配KMP算法
模式匹配KMP算法

  • 主串S“ACDACBACDDC”,模式串T“ACBACD”,匹配相比之下,BF算法匹配成功需匹配4次,而KMP算法只需匹配2次就可以,那么为什么KMP算法的步子可以跨这么大?是因为KMP算法中的next数组存放了模式串T出现重复字符的信息,利用已经部分匹配这个有效信息,保持i指针不回溯,通过修改j指针,让模式串尽量地移动到有效的位置,而避免模式串移动到无效位置(BF算法中2-3步均为无效位置)。

模式匹配KMP算法

  • 通过算法比较我们发现KMP算法与BF算法结构类似,最大的区别在于else里的j=next[j];也就是 i 不回溯,j 回溯到 next[ j ] 的位置,而不是每次都从零开始。
  • 那么,看到这里,我们也就知道了KMP算法原理就是利用 j=next[j] 来回溯,来减少比较次数,或者是说跳过一些不必要的比较,也就是迈大步子。

next数组是啥?

  • next数组是一个用来存放一个字符串的最长前缀和最长后缀相同的长度。按每一位对应的下标将对应长度值存于数组next中,如模式串T为“ababaca”,长度是7,所以next[0],next[1],next[2],next[3],next[4],next[5],next[6]分别计算的是 a,ab,aba,abab,ababa,ababac,ababaca的相同的最长前缀和最长后缀的长度。所以next[]={0,0,1,2,3,0,1};
  • 那我们的到了这个长度之后有什么用呢?next数组的下标与模式串T的下标是一致的(也就是下标 j ),也就是模式串T中每一位都可以对应其下标( j )在next数组中找到该位当前前缀与后缀的最长匹配长度,那么也就知道了,我们在当前位置下(也就是后缀)是否与模式串的开头(也就是前缀)有相同的部分、相同的部分是几位。那么我们举个例子当j=4时,此时模式串为“ababa”,那么此时显然有前缀:“aba”与后缀:“aba”相匹配,长度是3。那么我们将j=4带入next[ j ];结果是next[4]=3。
  • 那么也就是说,有了next数组,我们只需要知道下标就可以知道,当前前后缀的最长匹配长度。

next数组有啥作用?

  • 主串S“ACDACBACDDC”,模式串T“ACBACD”(如下图),当j=4是,模式串为“ACBAC”此时next[j]=next[4]=2,也就是说最大匹配长度为2,我们观察模式串“ACBAC”也不难发现前面的“AC”与后面的“AC”一致,那么在匹配的过程中(如下图所示),此时的指针j=4,所指的元素是“D”,然而“D”与主串中的"B"并不相等,那么,此时应该让j回溯,那么,回溯到什么位置呢?我们观察发现,“D”前面的AC先与主串匹配成功了,那么我们是不是只需要将,前缀的“AC”对齐,平移过来,就可以了呢!
  • 这就好比是后缀中的“AC”是探路人,告诉后方是否能匹配,下一次回溯时,前缀中的"AC"就可以直接上前来,这也就印证了为什么KMP算法的步子可以迈得大,因为有探路人探清楚了前面的情况,那后面的人就不需要小心翼翼的一步一步走,可以跨着走,跳着走。
    模式匹配KMP算法
  • 那么现在我们就知道了,后缀这个探路人,在发现前方能匹配的情况下,通过next数组找到后方的人,让其上前来。
  • 在代码上我们只需要 j=next[ j ];就可以实现了。(j回溯到的位置恰好是next[ j ])如下图:
    模式匹配KMP算法
  • 现在我们就可以归纳出next数组的作用:
  1. 探路人(后缀),找到后人(与后缀相匹配的前缀),并让其上前,怎么找?j=next[ j ]不就找到了吗! 如果next[ j ]=0的话,那说明没有后人(不存在与后缀相匹配的前缀),那只能重头开始。
  2. next数组也正是KMP算法的精髓所在,充分记录并利用探路人(后缀)获取的信息(已匹配信息),让算法能绕过很多不必要的匹配项,少走很多弯路。

如何让程序求出next数组?

模式匹配KMP算法

  • 1.如果对于值k,已有p0 p1, …, pk-1 = pj-k pj-k+1, …, pj-1,相当于next[j] = k。未完待续

模式匹配KMP算法

  • 2未完待续模式匹配KMP算法
  • 3未完待续模式匹配KMP算法

未完待续!

相关文章:

  • 2021-12-18
  • 2021-05-20
  • 2021-09-29
  • 2022-01-08
  • 2021-09-13
  • 2021-12-09
  • 2021-12-09
  • 2021-12-09
猜你喜欢
  • 2021-10-08
  • 2021-11-07
  • 2021-08-04
相关资源
相似解决方案