KMP算法
1、背景
KMP 算法是 D.E.Knuth、J,H,Morris 和 V.R.Pratt 三位神人共同提出的,称之为 Knuth-Morria-Pratt 算法,简称 KMP 算法。该算法相对于 Brute-Force(暴力)算法有比较大的改进,主要是消除了主串指针的回溯,从而使算法效率有了某种程度的提高。
2、求解next数组
按照搜索引擎方面的查找,似乎有两种计算模式。
模式串: ABCDABD
1、计算maxL数组
对于A,没有前后缀,所以 为0
对于AB,前缀为A,后缀为B,最大相同串长度为0
对于ABC,前缀为A,AB,后缀为C,BC,最大相同串长度为0
对于ABCD,前缀为A,AB,ABC,后缀为D,CD,BCD,最大相同串长度为0
对于ABCDA,前缀为A,AB,ABC,ABCD,后缀为A,DA,CDA,BCDA,最大相同串 A 长度为1
对于ABCDAB,前缀为A,AB,ABC,ABCD,ABCDA,后缀为B,AB,DAB,CDAB,BCDAB,最大相同串 AB 长度为2
对于ABCDABD,前缀为A,AB,ABC,ABCD,ABCDA,ABCDAB,后缀为D,BD,ABD,DABD,CDABD,BCDABD,最大相同串 长度为0
所以可得
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
Str | A | B | C | D | A | B | D |
maxL | 0 | 0 | 0 | 0 | 1 | 2 | 0 |
针对next数组与MaxL之间的关系
如果next[0]= 0, 则next[i] = maxL[i-1]+1
如果next[0]= -1, 则next[i] = maxL[i-1]
我们这边采取的是next[0]=0,可得
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
str | A | B | C | D | A | B | D |
maxL | 0 | 0 | 0 | 0 | 1 | 2 | 0 |
next | 0 | 1 | 1 | 1 | 1 | 2 | 3 |
2、直接求解next数组
计算规则:
当前下标为i,则查看 str[i-1] 与 str[next[i-1]-1]之间的值是否一致
如果一致,则 next[i] = next[i-1]+1
如果不一致,则 k=next[i-1]-1,
比较str[i-1] 与 str[k],迭代K,知道两个值一致,则 next[i] = next[k] + 1
如果比较到第一位都不相等,则next[i] = 1
如果直接求解next数组的话,则next[0]=0, next[1]=1是默认值,所以需要从2开始测算
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
str | A | B | C | D | A | B | D |
next | 0 | 1 |
当前i=2, str[i-1] = ‘B’, next[i-1] = next[1] = 1, 所以对比 str[1] 与 str[0],发现不一致,同时已经比较到头部,所以next[2] = 1
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
str | A | B | C | D | A | B | D |
next | 0 | 1 | 1 |
当前i=3, str[i-1] = ‘C’, next[i-1] = next[2] = 1, 所以对比 str[2] 与 str[0],发现不一致,同时已经比较到头部,所以next[3] = 1
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
str | A | B | C | D | A | B | D |
next | 0 | 1 | 1 | 1 |
当前i=4, str[i-1] = ‘D’, next[i-1] = next[3] = 1, 所以对比 str[3] 与 str[0],发现不一致,同时已经比较到头部,所以next[4] = 1
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
str | A | B | C | D | A | B | D |
next | 0 | 1 | 1 | 1 | 1 |
当前i=5, str[i-1] = ‘A’, next[i-1] = next[4] = 1, 所以对比 str[4] 与 str[0],发现一致,所以next[5] = next[4] + 1 = 2
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
str | A | B | C | D | A | B | D |
next | 0 | 1 | 1 | 1 | 1 | 2 |
当前i=6, str[i-1] = ‘B’, next[i-1] = next[5] = 1, 所以对比 str[5] 与 str[0],发现一致,所以next[6] = next[5] + 1 =3