代码随想录算法训练营第九天

KMP算法

学习指南

帮你把KMP算法学个通透!B站(理论篇)

帮你把KMP算法学个通透!(求next数组代码篇)

理论支撑:在找目标子串过程中,为了减少每次查找完都从开头重新查找的时间,KMP算法被开发出来,旨在减少冗余查找,每次查找失败回溯到最节约查找时间的位置。

原理

上图中能看到,遍历到文本及模式的第五个字符(从0开始算)时字符不匹配,但模式串的指针不会回到第一个字符,而是来到与文本串字符‘b’相同的下标2处,继续进行下一个字符的比较。

方法

        第一步:

        得到next数组,next数组的作用,就是利用最长前后缀找到具有部分相同前缀的字符之间的联系。tip:当前字符利用的是前一个字符的前缀表,前缀表中储存的是有联系字符的下标。

        代码随想录算法训练营第九天_第1张图片

上图中,可以在前缀表中看到,与‘f’有联系的字符是下标为2的‘b’,而0代表的是不存在有联系的字符,此时模式串的指针直接回到下标0的位置

代码如下:

def getNext(self, needle: str, m: int):
        j = 0
        next = [0]*m
        next[0] = j
        for i in range(1, m):
            while j > 0 and needle[j] != needle[i]:
                j = next[j - 1]
            if needle[i] == needle[j]:
                j += 1
            next[i] = j
        return next

        第二步:

        利用前缀表(next)数组在文本串中找到模式串:

        若字符匹配,则模式串指针向前直到末尾

        若字符不匹配,则进行前缀表查询,期间进行指针移动,移动到指针所指的模式串字符与文本串相同或下标为0为止

代码如下:

def strStr(self, haystack: str, needle: str) -> int:
        m =  len(needle)
        next = self.getNext(needle, m)
        print(next)
        i = 0
        for j, x in enumerate(haystack):
            if x == needle[i]:
                i += 1
                if i == m:
                    return j - m + 1
            else:
                while i > 0 and x != needle[i]:
                    i = next[i - 1]
                if x == needle[i]:
                    i += 1
        return -1

本题代码所使用的是28.找出字符串中第一个匹配项的下标

总结:

        这是我第一次学习KMP算法,文笔粗糙稍显难懂,如有不对还请指出,希望我们能从本次学习中收获更多。

你可能感兴趣的:(算法,leetcode,python)