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)
View Code

ttt

参考:https://blog.csdn.net/czywangye/article/details/88852702?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2

http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

原文地址:https://www.cnblogs.com/xxswkl/p/12688287.html