此算法的思想是直截了当的:将主串 S 中某个位置 i 起始的子串和模式串 T 相比较。即从 j=0 起比较 S[i+j] 与 T[j] ,若相等,则在主串 S 中存在以 i 为起始位置匹配成功的可能性,继续往后比较 ( j 逐步增 1 ) ,直至与 T 串中最后一个字符相等为止,否则改从 S 串的下一个字符起重新开始进行下一轮的 " 匹配 " ,即将串 T 向后滑动一位,即 i 增 1 ,而 j 退回至 0 ,重新开始新一轮的匹配。
![](https://p-blog.csdn.net/images/p_blog_csdn_net/lin_bei/9e2d7a511327402bbc7959c84ebd6f98.jpg)
![](https://p-blog.csdn.net/images/p_blog_csdn_net/lin_bei/33b15074cb1f4dcabbe3bb4c729fece8.jpg)
![](https://p-blog.csdn.net/images/p_blog_csdn_net/lin_bei/42983ca2a0314f3d82f83a771c6a4c32.jpg)
![](https://p-blog.csdn.net/images/p_blog_csdn_net/lin_bei/7eb3b9a6e6624a0a8fe8559ba1d42129.jpg)
![](https://p-blog.csdn.net/images/p_blog_csdn_net/lin_bei/fd21ec3847f94dd28f3efd5e49408167.jpg)
![](https://p-blog.csdn.net/images/p_blog_csdn_net/lin_bei/fe9a1d6bcb8f4e15944b3cffe6372744.jpg)
![](https://p-blog.csdn.net/images/p_blog_csdn_net/lin_bei/f6fd94b555f340ea8e7bb46ac5b69e78.jpg)
如果目标串和模式串在第m位(模式串的第m位)发生了不匹配,只需要分析模式串的前m位,我们就可以知道,在接下来的后1次比较中,前面长度为m-1的字符是否和目标串匹配。
(如果模式串的前m位中,长度为m-1的前缀和后缀匹配,那么此次比较中前面长度为m-1的字符和目标串匹配,反之不匹配)
举例:
目标串为D1D2 D3 D4 D5 D6
模式串为A1A2 A3 A4 A5 A6
下标: 0 1 2 3 4 5
在下标为5的位置发生了不匹配(目标串中是D6,模式串中是A6),如果模式串中A1 A2A3 A4 (长度为4的前缀)匹配A2 A3 A4 A5(长度为4的后缀),那么接下来的一次匹配中(把模式串右移一位)模式串的前面4位就能和目标串匹配了。且前面4个字符的比较可以直接跳过,直接比较模式串的A5和目标串的D6。
如果模式串中A1 A2 A3A4 不匹配A2 A3 A4A5,那么我们可以知道接下来的一次匹配肯定是会失败的。我们可以跳过这次比较。继续看模式串(A1 A2 A3 A4 A5)的长度为3的前缀是否匹配长度为3的后缀。
重复这一步骤,我们可以一直检查到长度为1的前缀和后缀是否匹配。
将这些能够匹配的前缀、后缀对记录下来,我们就知道在发生不匹配时,我们的模式串该右移到什么位置来和目标串继续进行匹配(以例子中的情况来说,如果长度为4的前缀、后缀对匹配,那么模式串应该右移1位再继续比较;如果长度为3的前缀、后缀对匹配,那么模式串应该右移2位再继续比较),而且继续匹配时,指向目标串的指针是不需要回溯的(继续从发生不匹配的位置开始进行比较)。
所以,我们可以将模式串的每一位对应的前缀、后缀对(可能会有不止一对)先计算保存起来,在匹配过程中,在哪一位发生了不匹配,我们查表就可以知道应该将模式串右移到什么位置来继续进行比较。这就是KMP算法的基本思想。
下标
|
0
|
1
|
2
|
3
|
4
|
T
|
a
|
b
|
c
|
a
|
c
|
next
|
-1
|
0
|
0
|
-1
|
1
|
下标
|
0
|
1
|
2
|
3
|
4
|
T
|
a
|
b
|
c
|
a
|
b
|
next
|
-1
|
0
|
0
|
-1
|
0
|
下标
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
T
|
a
|
b
|
a
|
b
|
c
|
a
|
a
|
b
|
c
|
next
|
-1
|
0
|
-1
|
0
|
2
|
-1
|
1
|
0
|
2
|
下标
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
T
|
a
|
b
|
C
|
a
|
b
|
C
|
a
|
d
|
next
|
-1
|
0
|
0
|
-1
|
0
|
0
|
-1
|
4
|
下标
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
T
|
a
|
d
|
C
|
a
|
d
|
C
|
a
|
d
|
next
|
-1
|
0
|
0
|
-1
|
0
|
0
|
-1
|
0
|
下标
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
T
|
a
|
b
|
a
|
b
|
c
|
a
|
a
|
b
|
c
|
(1) next
|
-1
|
0
|
-1
|
0
|
2
|
-1
|
1
|
0
|
2
|
(2) next
|
-1
|
0
|
0
|
1
|
2
|
0
|
1
|
1
|
2
|
(3) next
|
0
|
1
|
0
|
1
|
3
|
0
|
2
|
1
|
3
|
下标
|
0
|
1
|
2
|
3
|
4
|
T
|
a
|
b
|
c
|
A
|
c
|
(1)next
|
-1
|
0
|
0
|
-1
|
1
|
(2)next
|
-1
|
0
|
0
|
0
|
1
|
下标
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
T
|
a
|
d
|
C
|
a
|
d
|
C
|
a
|
d
|
(1)next
|
-1
|
0
|
0
|
-1
|
0
|
0
|
-1
|
0
|
(2)next
|
-1
|
0
|
0
|
0
|
1
|
2
|
3
|
4
|