一般的字符串比较算法是暴力匹配
当被比较字符串和比较字符串失配时 比较字符串的当前比较字符转到0
被比较字符串也转到上个开始匹配的位置+1
这样比较效率通常是极低的
KMP算法便是更快速高效的字符串比较算法
KMP算法关键是一个模式串的最长公共前后缀 明白了这个含义KMP算法算是理解了大半
**
最长公共前后缀
**
倘若有这样一个字符串"ABCBCA"
该字符串的前缀集合:
A,AB,ABC,ABCB,ABCBC
高字符串的后缀集合:
A,CA,BCA,CBCA,BCBCA
看的出该字符串的最长前后缀为A 长度为1
概念
上面对于字符串ABCBCA求出了最长公共前后缀的长度为1
那么对于目标串ABCBCD来说在匹配D失陪时 对于ABCBCA比较串后移多少位才能继续匹配(KMP算法是失配时保持被比较串的位置不变 后移比较串来进行字符串匹配的)
被比较串: ABCBCD…
比较串: ABCBCA
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
被比较串 | A | B | C | B | C | D | … |
模式串 | A | B | C | B | C | A |
看得出来在匹配D失配时 理应把比较串挪到最后继续匹配
我们在上面算出ABCBCA的最长公共串的长度为1
然后再来看看失配时比较串挪动后的位置和挪动前的位置的关系
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
---|---|---|---|---|---|---|---|---|---|---|---|
挪动前 | A | B | C | B | C | A | |||||
挪动后 | A | B | C | B | C | A |
我们看到重叠了一个字符 然而这个字符个数刚好是:
对于挪动前而言是最长的后缀公共串
对于挪动后而言则是最长的前缀公共串
因为我们计算出最长的公共前后缀长度为1 所以就没有比较再去比较其他情况了 直接比较最长前后缀都为1的情况即可
例子:
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
模式串 | A | B | C | A | B | C |
最长公共前后缀为ABC
长度为3
第一次匹配时
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
---|---|---|---|---|---|---|---|---|---|
匹配串 | A | B | C | A | B | D | E | A | |
模式串 | A | B | C | A | B | C | |||
失配时模式串要到的位置 | A | B | C | A | B | C |