给出一个字符串 S,考虑其所有重复子串(S 的连续子串,出现两次或多次,可能会有重叠)。
返回任何具有最长可能长度的重复子串。(如果 S 不含重复子串,那么答案为 ""。)
示例 1:
输入:"banana"
输出:"ana"
示例 2:
输入:"abcd"
输出:""
提示:
2 <= S.length <= 10^5
S 由小写英文字母组成。
解题思路:
二分查找 + Rabin-Karp 字符串编码。
我们可以把这个问题分解成两个子问题:
-
从
1
到N
中选取子串的长度L
; -
检查字符串中是否存在长度为
L
的重复子串。
Python代码:
class Solution:
def longestDupSubstring(self, s: str) -> str:
def search(m, mod):
h = 0
for i in range(m):
h = (h * 26 + nums[i]) % mod
al = pow(26, m, mod)
seen = {h}
for pos in range(1, n - m + 1):
h = (h * 26 - nums[pos - 1] * al + nums[pos + m - 1]) % mod
if h in seen:
return pos
seen.add(h)
return -1
n = len(s)
nums = [ord(c) - ord('a') for c in s]
l, r = 1, n
mod = 2 ** 63 - 1
pos = 0
while l <= r:
mid = (l + r) // 2
cur = search(mid, mod)
if cur != -1:
l = mid + 1
pos = cur
else:
r = mid - 1
return s[pos: pos+l-1]