459.重复的子字符串

给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。

示例 1:

  • 输入: "abab"
  • 输出: True
  • 解释: 可由子字符串 "ab" 重复两次构成。

示例 2:

  • 输入: "aba"
  • 输出: False

示例 3:

  • 输入: "abcabcabcabc"
  • 输出: True
  • 解释: 可由子字符串 "abc" 重复四次构成。 (或者子字符串 "abcabc" 重复两次构成。)

解法:KMP算法

如果一个字符串可以由重复子串构成,那么这个子串 是 它的最长相等前后缀 不包含的部分

例子:ababab,最长相等前后缀是abab,不包含ab,那么重复子串(如果有的话)是ab。

证明过程:

代码:

class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        if len(s) == 0:
            return False
        nxt = [0] * len(s)
        self.getNext(nxt,s)
        if nxt[-1] != 0 and len(s) % (len(s)-nxt[-1]) == 0:
            return True
        return False

    def getNext(self, nxt, s):
        nxt[0] = 0
        j = 0
        for i in range(1, len(s)):
            while j>0 and s[i] != s[j]:
                j=nxt[j-1]
            if s[i] == s[j]:
                j += 1
            nxt[i] = j
        return nxt

注意:

在找nxt数组的时候,i从1开始,而不是从0开始。

是比较s中的元素是否相同,而不是nxt中的。

总结:

这道题思路比较巧妙。

KMP算法还需要多看,多练习,去熟练。 

5月13日 重写:

class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        if len(s)==0:
            return False
        nxt=[0]*len(s)
        self.getNext(nxt,s)
        if s[-1]!=0 and len(s)%(len(s)-s[-1])==0:
            return True
        return False
        
    def getNext(self, nxt, s):
        j=0
        nxt[0]=j
        for i in range(1,len(s)):
            while j>=0 and s[i]!=s[j]:
                j=nxt[j-1]
            if s[i]==s[j]:
                j+=1
            nxt[i] = j
        return nxt

错误点:

上面那个function是if nxt[-1]!=0, 而不是if s[-1]!=0. 是看next数组的最后一个元素。

同理,下面也是 len(s)-nxt[-1],而不是len(s)-s[-1]

主要是把s和nxt数组搞混了。nxt数组是记录最长相等前后缀的数组,s是字符串。

还有,这个题里面的next数组是没有-1的版本,所以while是while j>0,而不是j>=0.

当j=0的时候,且s[i]!=s[j], 那么next[i]就一直等于j,也就是等于0. 直到有s[i]==s[j],j才+1,等于1.

while j>0是为了保证下面 回退的时候,用到的j=nxt[j-1]是可以实现的,如果j=0,那么没有nxt[j-1],就会出现问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值