KMP算法
KMP算法的关键和难点是next数组的构建,next数组是由模式串生成的状态转移数组,next[i]表示当模式串needle[i]与主串的的不匹配时,需要跳到needle[next[i]]进行比较,
class Solution: def strStr(self, haystack: str, needle: str) -> int: if needle == "": return 0 # 生成next数组,用于记录状态的转移 i, k, m = 0, -1, len(needle) # 初始值 pnext = [-1] * m # i指针从0开始到匹配串的末尾 # next[i]表示当needle[i]与haystack[h]不匹配时,这时需要状态转移,也就是说haystack[h]该与哪个needle[i]比较 # next[i]给出了答案,即haystack[h]与needle[next[i]]比较,即从i状态转移到next[i]状态,而k就等于next[i], # 也就是说k表示要转移到的状态,如果所有的状态是从0到len(needle)-1,则忽略了当模式串的第0个字符与主串不匹配 # 时,需要移动主串的情况(这时再移动模式串无效),所以将k初始化为-1, while i < m-1: # 如果k等于-1,则表示needle[i]前面不存在最长公共前后缀,此时需要直接跳到needle的开头进行比较,所以赋值为k+1为0 # 如果needle[i]等于needle[k],needle[k]表示needle[i](不含needle[i])的最长公共前后缀,k是其索引, # k+1是下一个要比较的索引,所以要加一, # if k == -1 or needle[i] == needle[k]: i += 1 k += 1 pnext[i] = k # 这里结束时,needle[i]和needle[k]还没有比较,但是needle[i-1](包含needle[i-1])的最长公共前后缀已经知道了, # 是needle[k-1],所以下一步首先要比较needle[i]和needle[k]是否相等,如果相等,则最长公共前后缀加1,否则改变k, # 如果下一步比较的时候,k不等于-1,并且needle[i]不等于needle[k],则此时必须找到以needle结尾的最长公共前后缀, # pnext[k]表示needle[k]的最长公共前后缀的长度,当pnext[k]作为索引时,表示最长公共前后缀的下一个元素,而这里我们 # 正是要比较下一个元素与needle[i]是否相等, else: k = pnext[k] print(pnext) # matching h, j = 0, 0 n = len(haystack) # 两个指针必须小于字符串长度 # 结束只有两种情况,一种是主串都遍历完了,没有匹配的, # 另一种是模式串遍历完了,有匹配的, while h < m and j < n: # 如果h等于-1表示对模式串needle从头开始比较,因为h+1等于0,而主串haystack也要后移一位 # 如果needle[h] == haystack[j]表示当前匹配相等,则指针都向后移一位,比较下一个, if h == -1 or needle[h] == haystack[j]: h, j = h + 1, j + 1 # 如果不相等,即当前模式串和主串不相等时,则对模式串进行状态转移,确定和主串比较的模式串中的下一个字符 else: h = pnext[h] # 比较结束后,如果匹配串的值指向了末尾再加1,则说明匹配成功,返回 if h == m: return j - h return -1 # 作者:jia - zhi - tong - 1 # 链接:https: // leetcode - cn.com / problems / implement - strstr / solution / kmpshi - xian - by - jia - zhi - tong - 1 / # 来源:力扣(LeetCode) # 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 if __name__ == '__main__': solution = Solution() # result = solution.strStr(haystack='BBCABCDABABCDABCDABDE',needle='ABCDABD') # result = solution.strStr(haystack='BBCABCDABABCDABCDABDE',needle='ABCDABD') # result = solution.strStr(haystack='BBCABCDABABCDABCDABDE',needle='ABCABCFE') result = solution.strStr(haystack='BBCABCDABABCDABCDABDE',needle='ABABAB') print(result)
ttt
http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html