一、设计思想
1、KMP的核心
解决的BF算法中主串回退的问题,提高了效率,所以KMP中最核的问题是找到模式串要回退的位置
2、回退思想
(1)在此之前让大家明白一个概念:
最大前缀和最大后缀相等:在串中,从第一个下标位置开始找到一个元素与这个元素到失配点前一个位置完全相等的部分。
举例:
KMP的思想:
(1)当进行匹配时匹配成功,那就让继续向下遍历进行(2),如果匹配失败,主串不变,模式串又从0开始匹配。
(2)有一次匹配成功后继续依次进行匹配,如果再次匹配失败,那么我们就让模式串回退到最大后缀和最大前缀相等的位置。因为不相等的部分我们知道他进行匹配是一定失败的,所以我们减少这些不必要的操作。
(3)我们可以这样理解,对于KMP来说,我们是用整体去匹配,可以省去很多步骤
KMP遍历图解:
用主串的3个后缀和模式串的3个前缀进行匹配,匹配成功,在进行这一步的时候,我们可以认为这三个元素已经匹配完成直接用3号位置的j与i进行匹配
所以现在我们发现,KMP最终要解决的就是找到最大前缀和最大后缀相等的位置,也就是模式串要回退的最佳位置
3、next的求解
next是什么???
我们从上面已经知道KMP的核心是解决每一个位置的最大前缀和最大后缀相等的个数,我们把这些个数存放在一个数组next中。
(1)手动计算next的值
- 对于第一个位置和第二个位置,我们给它赋为定值,因为她们前面不存在最大前缀和最大后缀,所以我们发现要找到最大前缀和最大后缀至少要有3个元素
- 从第一个下标位置开始找到一个元素与这个元素到失配点前一个位置完全相等的部分的元素个数
(2)理论分析
当串中元素相等时
首先我们要知道计算每个元素的next时,必须知道在此元素之前的所有元素的next值。
最大前缀和最大后缀相等的个数我们记作k。
由上图,我们来计算next(5)=???
- 我们来这样做,从t(0)位置开始到t(k)位置与t(j-k)位置到t(j-1)位置相等的部分,但对于必须是前缀从0号下标开始,后缀从当前元素的前一个位置结束
- 对于下图找next[5]来说,t(0)==t(j),也就是t(k)==t(j),所以最大前缀和最大后缀相等的个数是1,所以next[5]=1;
- 如果t(0)==t(j),那我们如何求next[6]=?
- 我们继续找从t[0]位置开始到t[k]位置与t(j-k)位置到t(j-1)位置相等的部分,这时候,我们发现k的位置向后移了一位,j-1的位置也变成了j