简介:
KMP算法是一种改进的字符匹配算法。由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。 它的核心思想是,通过一个next[]数组,在匹配失败后,减少字符移动的距离,达到快速匹配的目的。
要想彻底理解KMP算法,必须要知道几个核心概念: 最长相同前后缀:即从前往后找,从后往前找,相同前后缀中最长的字符串。 Next[]数组存放的是子字符串最长前后缀的长度。
比如 ABCDABD 的next[]数组
子字符串 | 前缀 | 后缀 | 最长相同前后缀 | 最长相同前后缀长度 | |
---|---|---|---|---|---|
next[1] | A | 0 | |||
next[2] | AB | A | B | 0 | |
next[3] | ABC | A,AB | C,BC | 0 | |
next[4] | ABCD | A,AB,ABC | D,CD,BCD | 0 | |
next[5] | ABCDA | A,AB,ABC,ABCD | A,DA,CDA,BCDA | A | 1 |
next[6] | ABCDAB | A,AB,ABC,ABCD,ABCDA | B,AB,DAB,CDAB,BCDAB | AB | 2 |
next[7] | ABCDABD | A,AB,ABC,ABCD,ABCDA,ABCDAB | B,BD,ABD,DABD,CDABD,BCDABD | 0 |
关于next[]的作用,举个栗子:
假如有字符串α= ABABC***,要查找的字符串为β= AB*ABD
当匹配到这种情况时=> α: **** AB **** ABC ***
β: AB **** ABD ***
β的第9个字符与α的第13个字符不匹配,那么就要移动β字符。
由题设可知β的前8个字符中,1 ~ 2之间的字符(AB)=7~8之间的字符(AB)是相同的,即next[8]=2。
α的第5 ~ 12之间的字符(ABAB)和β的1~8之间的字符(ABAB)是匹配的,匹配的长度是8。
由此可知,α的11 ~ 12之间的字符(AB)与β的7~8之间的字符(AB)是相等的
=> α的11 ~ 12之间的字符(AB)=β的1~2之间的字符(AB)
所以我们只要将β字符串向前移动的长度=已匹配的长度8 -next[8](β1~8之间字符最长的相
同前后缀(AB)长度)=6;即只要将β向前移动6位
α: **** AB **** ABC ***
β: AB * *** ABD ***
从β的第3个字符开始匹配,从而省去了前两个的匹配时间