【leetcode】-1044. Longest Duplicate Substring 最长重复子串

Longest Duplicate Substring

  • 题目
  • 暴力法
    • python代码
  • 二分法+Rabin-Karp
    • python代码

题目

Given a string S, consider all duplicated substrings: (contiguous) substrings of S that occur 2 or more times. (The occurrences may overlap.)

Return any duplicated substring that has the longest possible length. (If S does not have a duplicated substring, the answer is “”.)

Example 1:

Input: “banana”
Output: “ana”

Example 2:

Input: “abcd”
Output: “”

Note:

2 <= S.length <= 10^5
S consists of lowercase English letters.

暴力法

面试的时候遇到这题了,然后刚开始没注意,以为是求最长子串,说了最长子串的思路后面试官又说是求最长重复子串,但是想着用动态规划,但是找不到状态方程,又想到最简单的穷举法,面试官还给提示了,最后也没写出来,可能面试挂了吧。

也不知道为什么,面试的时候大脑一片空白,但是下来自己理清思路后暴力法也是可以解决的,题目给的示例能过,但最后还是超时了。

思路其实很简单,将子串从1到n一个一个比较。开始以一个字母遍历,看哪个子串的重复数最大,b,a,n,a,n,a,一个字符是"a"的重复数最大,将其存到一个数组中保存;然后看二个字符的,ba,an,na,an,na,将"an"存到数组中,以此类推。

python代码

class Solution(object):
    def longestDupSubstring(self, S):
        """
        :type S: str
        :rtype: str
        """
        if not S:
            return ""
        res = []
        n = len(S)
        j = 1
        while j < n:
            d = dict()
            for i in range(n):
                k = i + j
                if k < n+1:
                    if S[i:k] in d:
                        d[S[i:k]] += 1
                    else:
                        d[S[i:k]] = 1
            mmax = 1
            for k, v in d.items():
                if v > mmax:
                    mmax = v
                    temp = k
            if mmax > 1:
                res.append(temp)
            else:
                res.append("")
            j += 1

        c = 0
        for s in res:
            if len(s) >= c:
                c = len(s)
                t = s
        return t

时间复杂度为O(n^2),空间复杂度为O(n).

二分法+Rabin-Karp

Rabin-Karp算法是字符串查找中的一种思想,将字符串转化为哈希值进行计算,然后通过减去首字母的值再加上一个字母的值比较是否重复。
比如计算128进制的“bbc”:
b * 128^2 + b * 128^1 + c = 1605632 + 12544 + 99 = 1618275
然后减去第一个b: - b * 128^2, 然后向后移动一位: * 128 , 再加上最后一个字母 , 即: (1618275 - b * 128^2) * 128 + x 的值, 再与6447715(bbc)相比. 这种计算方式也叫"滚动哈希".

python代码

class Solution(object):
    def longestDupSubstring(self, S):
        """
        :type S: str
        :rtype: str
        """
        def search(m,MOD):
            h = 0
            for i in range(m):
                h = (h*26+nums[i])%MOD
            s = {h}
            aL = pow(26,m,MOD)
            for pos in range(1,n-m+1):
                h = (h*26-nums[pos-1]*aL+nums[pos+m-1])%MOD
                if h in s:
                    return pos
                s.add(h)
            return -1
            
        if not S:
            return ""
        n = len(S)
        nums = [ord(c)-ord('a') for c in S]
        l = 1
        r = n
        pos = 0
        MOD = 2**63 -1
        while l <= r:
            m = (l+r)//2
            cur = search(m,MOD)
            if cur!=-1:
                l = m+1
                pos = cur
            else:
                r = m-1
        return S[pos:pos+l-1]

时间复杂度为O(nlogn),空间复杂度为O(n)。

你可能感兴趣的:(LeetCode)