LeetCode 28 KMP next数组

LeetCode 28 KMP next数组

这题的难度是一个easy,可能KMP算法已经人尽皆知了吧。

KMP

有关KMP和暴力匹配,简单对比一下
S : ABCDABCABCDABCD
P : ABCDABD
现在发现了匹配失败
暴力法:P后移一位
S : ABCDABEABCDABCD
P :  ABCDABD
匹配完耗时 O ( M ∗ N ) O(M*N) O(MN)
KMP:后移next位
S : ABCDABEABCDABCD
P :      ABCDABD
匹配完耗时 O ( M + N ) O(M+N) O(M+N)
区别就是,暴力法匹配失败后pattern后移一位,KMP匹配失败后pattern后羿next[j]位
S : ABCDABCABCDABCD
P : ABCDABD

这里就不解释KMP了,网上一大堆

next数组

S : ABCDABEABCDABCD
P : ABCDABD
在匹配失败后,P的前6个字母是匹配成功的,这时p里面的字符D会指向字符C

-1000-102
ABCDABD

分析

上面这个next数组,如果第一个A就匹配失败,从头再来,如果第二个D匹配失败,D前面的AB一定匹配成功,所以D会指向C,下标为2的字符

code

class Solution:
    def strStr(self, s1: str, s2: str) -> int:
        nextn = [0] * len(s2)
        
        return self.kmp(s1, s2, nextn)
        # print(nextn)
    
    def kmp(self, s1: str, s2: str, nextn: list) -> int:
        if not s2:
            return 0
        # 求s1中s2第一次出现的位置
        i, j = 0, 0
        k, ans = -1, 0
        nextn[0] = -1
        lens2 = len(s2)
        # 先生成next数组,这个过程就是那s2匹配S2它自己
        while j < lens2:
            while k != -1 and s2[j] != s2[k]:
                k = nextn[k]
            j += 1
            k += 1
            if j < lens2 and k < lens2:
                if s2[j] != s2[k]:
                    nextn[j] = k
                else:
                    nextn[j] = nextn[k]
        # end_while
        # 匹配过程
        j = 0
        while i < len(s1):
            if j != -1 and j == lens2:
                return i - j
            while j != -1 and s1[i] != s2[j]:
                j = nextn[j]
                
            i += 1
            j += 1
        #end_while
        if j == lens2:
            return i - j
        else:
            return -1

总结

KMP就是充分利用已经匹配成功的前缀,来跳过已知必定失败的方案

欢迎一起来参与leetcode刷题项目

刷题的GitHub: github链接.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值