- 1044. Longest Duplicate Substrin
- longest substring without repeat
- 3. Longest Substring Without Rep
- 2022-08-11 真实题目
- 【算法】Longest Palindromic Substrin
- LeetCode #1044 Longest Duplicate
- LeetCode-string-Longest Substrin
- [LeetCode] No.3 Longest Substrin
- [LeetCode题解] 3. Longest Substrin
- 每日算法之LeetCode 3:Longest Substrin
这道就是Rolling Hash + Binary Search的组合。
周赛的时候笔者想到了Rolling Hash, 然后并没有想到加binary search进行优化
写了两个naive的solution 都TLE了,然而虽然这题没写出来,这次周赛还是排在300名左右不算差。
要 对Rolling hash再熟一点,我下来之后写的代码在减去最高位的时候出一个bug调了好久。
当减去最高位时, 我傻傻的直接mod (26 ** len)了。
应该是减去 (26 ** len) 再mod (MOD).
不能mod (26 ** len)的。
The idea is similar to Lee215's post.
Using rolling hash to avoid recalculation of the hash key.
Using binary search to find the longgest length.
class Solution {
Long MOD;
public String longestDupSubstring(String S) {
int N = S.length();
int max = 0;
String ans = "";
MOD = 1000000007L;
int l = 0, r = N - 1;
//binary search
while (l <= r) {
int mid = l + (r - l) / 2;
boolean breakout = false;
Map<Long, List<Integer>> map = new HashMap<>(); // the List<Integer> store a list of indexes which have the same hashCode
long prev = 0;
long pow26 = calcPower26(mid);
for (int i = 0; i + mid - 1 < N; i++) {
long code = calc(S, i, mid, prev, pow26); // calculate hashcode
if (map.containsKey(code)) {
for (int m : map.get(code)) { // iterate thru the list and verify the match to deal with hash collision.
if (S.substring(i, i + mid).equals(S.substring(m, m + mid))) {
breakout = true;
if (mid > max) {
max = mid;
ans = S.substring(i, i + mid);
}
break;
}
}
}
if (breakout) break;
map.putIfAbsent(code, new ArrayList<>());
map.get(code).add(i);
prev = code; //log prev for next hashcode calculation.
}
if (breakout) l = mid + 1;
else r = mid - 1;
}
return ans;
}
private long calc(String s, int start, int len, long prev, long pow26) {
long ans = 0L;
if (start == 0) { // first time calcuation
for (int i = 0; i < len; i++) {
ans *= 26L;
ans += (long) (s.charAt(start + i) - 'a');
ans %= MOD;
}
} else { // defer from previous result.
ans = prev * 26L;
ans += (long) (s.charAt(start + len - 1) - 'a');
ans -= (s.charAt(start - 1) - 'a') * pow26; // 在这里写了一个bug, 我直接用ans % pow26了。
}
ans %= MOD;
if (ans < 0L) ans += MOD;
return ans;
}
private long calcPower26 (int n) {
if (n == 0) return 1L;
if (n == 1) return 26L;
long half = calcPower26( n / 2);
long ans = (half * half) % MOD;
ans *= calcPower26(n - (n / 2) * 2);
return ans % MOD;
}
}
网友评论