Skip to content

Commit c19ee1d

Browse files
committed
Add solution #1044
1 parent 75aa6de commit c19ee1d

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# 1,117 LeetCode solutions in JavaScript
1+
# 1,118 LeetCode solutions in JavaScript
22

33
[https://leetcodejavascript.com](https://leetcodejavascript.com)
44

@@ -851,6 +851,7 @@
851851
1041|[Robot Bounded In Circle](./solutions/1041-robot-bounded-in-circle.js)|Medium|
852852
1042|[Flower Planting With No Adjacent](./solutions/1042-flower-planting-with-no-adjacent.js)|Medium|
853853
1043|[Partition Array for Maximum Sum](./solutions/1043-partition-array-for-maximum-sum.js)|Medium|
854+
1044|[Longest Duplicate Substring](./solutions/1044-longest-duplicate-substring.js)|Hard|
854855
1047|[Remove All Adjacent Duplicates In String](./solutions/1047-remove-all-adjacent-duplicates-in-string.js)|Easy|
855856
1051|[Height Checker](./solutions/1051-height-checker.js)|Easy|
856857
1071|[Greatest Common Divisor of Strings](./solutions/1071-greatest-common-divisor-of-strings.js)|Easy|
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* 1044. Longest Duplicate Substring
3+
* https://leetcode.com/problems/longest-duplicate-substring/
4+
* Difficulty: Hard
5+
*
6+
* Given a string s, consider all duplicated substrings: (contiguous) substrings of s that occur 2
7+
* or more times. The occurrences may overlap.
8+
*
9+
* Return any duplicated substring that has the longest possible length. If s does not have a
10+
* duplicated substring, the answer is "".
11+
*/
12+
13+
/**
14+
* @param {string} s
15+
* @return {string}
16+
*/
17+
var longestDupSubstring = function(s) {
18+
const MOD = 1e9 + 7;
19+
const BASE = 26;
20+
let left = 1;
21+
let right = s.length - 1;
22+
let result = '';
23+
24+
while (left <= right) {
25+
const mid = Math.floor((left + right) / 2);
26+
const candidate = checkLength(mid);
27+
if (candidate) {
28+
result = candidate;
29+
left = mid + 1;
30+
} else {
31+
right = mid - 1;
32+
}
33+
}
34+
35+
return result;
36+
37+
function checkLength(len) {
38+
let hash = 0;
39+
const seen = new Map();
40+
let basePow = 1;
41+
for (let i = 0; i < len - 1; i++) {
42+
basePow = (basePow * BASE) % MOD;
43+
}
44+
45+
for (let i = 0; i < len; i++) {
46+
hash = (hash * BASE + (s.charCodeAt(i) - 97)) % MOD;
47+
}
48+
49+
seen.set(hash, [0]);
50+
51+
for (let i = 1; i <= s.length - len; i++) {
52+
hash = (hash - ((s.charCodeAt(i - 1) - 97) * basePow) % MOD + MOD) % MOD;
53+
hash = (hash * BASE + (s.charCodeAt(i + len - 1) - 97)) % MOD;
54+
if (seen.has(hash)) {
55+
const prevIndices = seen.get(hash);
56+
const currSubstr = s.slice(i, i + len);
57+
for (const prev of prevIndices) {
58+
if (s.slice(prev, prev + len) === currSubstr) {
59+
return currSubstr;
60+
}
61+
}
62+
prevIndices.push(i);
63+
} else {
64+
seen.set(hash, [i]);
65+
}
66+
}
67+
return '';
68+
}
69+
};

0 commit comments

Comments
 (0)