代码随想录算法训练营第九天|28. 实现 strStr(), 459.重复的子字符串

通过今天的学习, 了解使用 KMP算法做字符串匹配, 字符串的 next 数组定义以及实现算法。收获颇丰。

算法基础解释:第四章 字符串part02

28. 实现 strStr()

思路:未接触KMP算法之前, 第一想法是通过slicing window来判断, 逻辑很简单, 时间复杂度 O(m*n). 学习KMP之后, 发现这道题是典型的KMP算法题。 next 数组我比较习惯右移一位, next[0]  = -1

难点: 先学算法在尝试实现

class Solution:
    def get_next_group(self, s: str) -> List[int]:
        next_list = [0] * len(s)
        j = 0 # 前缀最后一位下标
        i = 1 # 后缀第一位下标
        while i < len(s):
            if j > 0 and s[i] != s[j]:
                j = next_list[j-1]
            elif s[i] == s[j]:
                j += 1
                next_list[i] = j
                i = i+1
            else:
                i += 1
        return next_list
    
    def strStr(self, haystack: str, needle: str) -> int:
        next_list = self.get_next_group(needle)
        next_list[1:] = next_list[0:-1]
        next_list[0] = -1
        i, j = 0, 0
        while i < len(haystack):
            if haystack[i] == needle[j] or j == -1:
                i += 1
                j += 1
            else:
                j = next_list[j]

            if j >= len(needle):
                return i-len(needle)
        return -1

459.重复的子字符串

思路: 第一想法也是 brute force 把所有的substring 尝试一遍。 不过也可以巧妙的运用KMP 算法。 先计算next 数组。 如果 string 是有substring 复制n 次出来的, 那么next 数组的最后一位满足大于或等于 len(s) / 2。 并且 len(s) - next[-1] 一定可以被 len(s) 整除, 而且除数为n。 

难点: 第一次提交没有考虑 len(s) - next[-1] 被 len(s) 整除的情况, 导致有case 出错。

class Solution:
    def get_next_group(self, s: str) -> List[int]:
        next_list = [0] * len(s)
        j = 0 # 前缀最后一位下标
        i = 1 # 后缀第一位下标
        while i < len(s):
            if j > 0 and s[i] != s[j]:
                j = next_list[j-1]
            elif s[i] == s[j]:
                j += 1
                next_list[i] = j
                i = i+1
            else:
                i += 1
        return next_list

    def repeatedSubstringPattern(self, s: str) -> bool:
        next_list = self.get_next_group(s)
        if next_list[-1] < len(s) / 2:
            return False
        elif len(s) % (len(s)-next_list[-1]) !=0:
            return False
        else: 
            return True 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值