leetcode1044. 最长重复子串

滑窗:
枚举起点,如果符合尝试扩大窗口
不符合的时候缩小窗口
这样每个起点的最长重复子串都计算了一遍

def longestDupSubstring(self, s):
        """
        :type s: str
        :rtype: str
        """
        n = len(s)
        l, r = 0, 1
        _max, res = 0, ""
        while r <= n:
            if s[l:r] in s[l + 1:]:
                if r - l > _max:
                    _max, res = r - l, s[l:r]
                r += 1
            else:
                l += 1
        return res

Rabin-Karp 算法
不要每次都去一个字符一个字符地比较子串和模式串,而是维护一个滑动窗口,运用滑动哈希算法一边滑动一边计算窗口中字符串的哈希值,拿这个哈希值去和模式串的哈希值比较,这样就可以避免截取子串,从而把匹配算法降低为 O(N)
这题还用到了二分来快速的查找最长字串的长度应该是多少

def longestDupSubstring(self, s):
        """
        :type s: str
        :rtype: str
        """
        base = 26                                       #找好一对base和mod,防止碰撞
        mod = 10**13+1117
        arr = [ord(c)-ord('a') for c in s]              #用数组存,方便查找
        def check(m,base,mod):
            number = 0
            l = 0
            seen = set()
            rem = pow(base, m-1, mod)                    #注意这里取余,否则计算量超大
            for i in range(m-1):
                number = (number*base + arr[i])%mod      #注意这里取余,否则计算量超大
            for i in range(m-1,len(s)):
                number = (number*base + arr[i])%mod      #注意这里取余,否则计算量超大
                if number in seen:
                    return i
                else:
                    seen.add(number)
                number = (number - rem*arr[l])%mod       #注意这里取余,否则计算量超大
                l += 1
            return -1
        l,r = 1,len(s)-1
        end = -1
        while l <= r:                                       #二分查找长度
            m = l + (r-l)//2
            idx = check(m,base,mod)                         #返回的是末尾下标
            if idx != -1:
                l = m + 1
                length = m
                end = idx
            else:
                r = m - 1
        return s[end-length+1:end+1] if end != -1 else ""  #注意这里判断end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值