KMP算法

来源:互联网 发布:mac双系统卸载 编辑:程序博客网 时间:2024/06/06 00:45

KMP算法是一种处理模式匹配问题的一种高效算法,其对于任何模式和目标序列,都可以在线性时间内完成匹配查找且不会发生退化。下面我们通过一个实例来讲解KMP算法。

主串:b    a   b   c   b   a   b   c   a   b   c   a   a   b   c   a   b   c   a   b   c   a   c   a   b   c模式串:a   b   c   a   b   c   a   c   a   b

最原始的方法,那就是我们从初始位置开始比对:
这里写图片描述

1)匹配:那我们主串模式串相对位置不变,比较位置都后移一位继续比对。

2)不匹配:那我们模式串相对于主串整体后移一位,从初始位置重新比对。


那对于KMP算法呢,我们可以这么理解我们例子中的模式串有重复的地方a b c ||a b c a c a b所以我们在比对的时候之前的前缀匹配过的话,那我们直接就可以跳过匹配过得部分,直接从下个位置开始,这也是我们KMP算法的思想所在。如下图:
这里写图片描述

那么我们的问题来了,如何确定每次匹配不成功要后移多少呢?

由此我们引入next数组,next[i]数组中存储的是位置1到位置i-1最长的公共子串的长度K,那么i-1减去next[i]就是当主串[i]与模式串[i]不匹配时,我们要移动的距离了。

此时分为两种情况:
1)模式串[i]和模式串[K+1]不相等:

这里写图片描述

此时i前面的公共子串长度为K,那么next[i]=K
2)模式串[i]和模式串[K+1]相等:

这里写图片描述

此时next[i]=next[K+1],原因如下图所示:

这里写图片描述

可以看到第二行不匹配后,我们直接从比较位置的后面开始比较,因为此处和模式前缀相同,此处不匹配那么前缀也一定不匹配,所以直接略过从后面重新比对。

下面我们给出计算例子中next[]的过程:
1. 首先我们把初始的next[1]=-1,
2. 接下来next[2],即a b的next值:
这里写图片描述
模式串[2]位置之前的公共子串长度为0,所以next[2]=0
3. 接下来next[3],即a b c的next值:
这里写图片描述
模式串[3]位置之前的公共子串长度为0,所以next[3]=0
4. 接下来next[4],即a b c a的next值:
这里写图片描述
模式串[4]位置之前的公共子串长度为0,但是模式串[4]与模式串[1]相等,所以next[4]=next[1]=-1
5. 接下来next[5],即a b c a b的next值:
这里写图片描述
模式串[5]位置之前的公共子串长度为1,但是模式串[5]与模式串[2]相等,所以next[5]=next[2]=0
6. 接下来next[6],即a b c a b c的next值:
这里写图片描述
模式串[6]位置之前的公共子串长度为2,但是模式串[6]与模式串[3]相等,所以next[6]=next[3]=0
7. 接下来next[7],即a b c a b c a的next值:
这里写图片描述
模式串[7]位置之前的公共子串长度为3,但是模式串[7]与模式串[4]相等,所以next[7]=next[4]=-1
8. 接下来next[8],即a b c a b c a c的next值:
这里写图片描述
模式串[8]位置之前的公共子串长度为4,所以next[8]=4
后面不再赘述。

注:要注意区分是模式串与主串不匹配,还是模式串内部的不匹配。