KMP是一个用于字符串匹配的算法,用于求解串str2是否在串str1中出现并返回出现的位置(str1的长度>=str2的长度)
由于<cstring>里内置的子串查找函数时间复杂度太高(BF算法时间复杂度O(n*m)),所以数据过大时得手写kmp(O(n+m))
先理清楚2个概念
1.前缀和后缀
这是百度百科的解释
汉语里指在词根前面的构词成分。如“阿哥”、“阿姨”中的“阿”,英文中指一个英语单词可以分为三个部分:前缀(prefix),词根(stem)及后缀(suffix)。单词中位于词根前面的部分就是前缀。前缀,可以改变单词的意思。
引申到串里,如果串的长度为leng ,那这个串的前缀就可以是从str[0]到str[leng-1]中的任何一组
比如说一个串abcdef 那么它的前缀和后缀可以是下面几种情况
前缀 后缀
abcde bcdef
abcd cdef
abc def
ab ef
a f
2.next数组
这个数组是用来记录str2各个位置与str2其他位置的匹配信息的
比如说一个串str2 = "abcdabce",str1 = "abcdabcd******"
如果我们在和str1匹配的过程中已经确定匹配了"abcdabc"
然后只需要确定str1的下一个字符是"e"就能确定str2在str1中出现过了
但是现实总是骨感的,偏偏str1下一个字符是' d',匹配失败
传统的算法是又从str1第二个字符'b'开始,str2从str2第一个字符'a'开始匹配.这样时间就花费的很多,因为我们可以直接看出来,匹配失败后,str1可以从第一个'*'开始,str2可以从第二个'a'(str2[4])开始"再续前缘" ,而所谓的next就是储存这个"再续前缘"的位置信息的,因为我们发现,如果我们让next[7](str2字符"e"的位置)指向next[3](str2字符"d"的位置),那么,这样我们可以在上述匹配失败的时候让str2从第四个字符重新开始匹配,而不是回到第1个字符
而这个字符'd'的位置,正好就是字符'e'的前缀和后缀相同的字符数(都是"abc"),也就是当'e'匹配失败后就跳到'd'
以下内容转自阮一峰的网络日志