LC.P1044[最长重复子串]

方法一:字符串哈希+二分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution {
static final int hash = 1313131;
long[] h, p;
int n;

public String longestDupSubstring(String s) {
n = s.length();
h = new long[n + 1]; // 哈希数组
p = new long[n + 1]; // 次方数组
p[0] = 1;
for (int i = 1; i <= n; ++i) {
p[i] = p[i - 1] * hash;
h[i] = h[i - 1] * hash + s.charAt(i - 1);
}
String ans = "";
int left = 0, right = n - 1;
while (left < right) {
int mid = left + right + 1 >> 1;
String t = check(s, mid);
if (!t.isEmpty()) left = mid;
else right = mid - 1;
ans = t.length() > ans.length() ? t : ans;
}
return ans;
}

private String check(String s, int length) {
Set<Long> set = new HashSet<>();
for (int i = 1; i + length - 1 <= n; ++i) {
int j = i + length - 1;
long cur = h[j] - h[i - 1] * p[j - i + 1];
if (set.contains(cur)) return s.substring(i - 1, j);
set.add(cur);
}
return "";
}
}
  • 时间复杂度:$O(nlogn)$
  • 空间复杂度:$O(n)$