#KMP如何移动 获取next数组 KMP算法 时间复杂度
##KMP如何移动
KMP相对于传统的BF算法,改进了字符串移动的规则,传统的BF字符匹配算法没用充分利用到已经匹配过的字符的信息,每次只移动一位,因此效率不高,而KMP引入一个next数组(有效的前缀),充分利用匹配过的信息,加快了移动的效率(增加了移动的距离)。
举个例子:
1
2
| target string:ABCDAB-ABCDABCDABDE
pattern string:ABCDABD
|
pattern的next数组:
开始匹配:
第一次匹配到’-‘和’D’不匹配,根据next数组和最后一个匹配成功的字符,
1
2
| ABCDAB-ABCDABCDABDE
ABCDABD
|
pattern右移:
这样移动可以让已经匹配过的target的后缀对齐pattern的前缀,所以6-2=4,右移4位,前缀AB对齐已匹配的后缀AB
1
2
| ABCDAB-ABCDABCDABDE
ABCDABD
|
’-‘和’C’不匹配,同理,右移2-0=2
1
2
| ABCDAB-ABCDABCDABDE
ABCDABD
|
一开始就不匹配,右移一位
1
2
| ABCDAB-ABCDABCDABDE
ABCDABD
|
‘D’和’C’不匹配,6-2=4
1
2
| ABCDAB-ABCDABCDABDE
ABCDABD
|
匹配成功。
##获取next数组
以模式串AGCTAGCAGCTAGCTG为例
第一个前面没有字符,所以与前缀匹配的长度肯定是0
因为’G’!=’A’,所以G位置的next数组也是0,同理,C,T位置的next数组的值也是0
‘A’==’A’,说明这个位置存在一个字符与模式串的前缀匹配,且长度是1
每正确匹配一个,长度都加1
到了第7位A的时候,没有与第三位的T匹配,现在已经匹配的前缀是AGC,任意子后缀和A组成的前缀(GCA,CA)都不能匹配模式串的前缀,因此,我们从这个位置从头开始匹配
我们又再次匹配失败,这时,已经匹配的前缀是 AGCCTAGC,任意子后缀和T组成的前缀中,AGCT是能匹配模式串前缀的一个最长串,所以,T处的next值是4,同理可得G处是0
##KMP算法
##时间复杂度
pattern处理时间是O(strlen(pattern)),匹配时间O(strlen(target)),总时间O(M+N)
sicily1282使用kmp算法
参考文档:
1.字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法一网打尽
2.KMP算法的前缀next数组最通俗的解释,如果看不懂我也没辙了
3.字符串匹配的KMP算法