To find the longest repeating substring, we can use binary search on the substring length and check for duplicates using a rolling hash (Rabin-Karp). This efficiently narrows down the maximum length by checking if any substring of a given length repeats.
classSolution {
public:int longestRepeatingSubstring(string s) {
int n = s.size(), l =1, r = n, ans =0;
while (l <= r) {
int m = (l + r) /2;
unordered_set<longlong> seen;
longlong h =0, a =26, mod =1e9+7, pow =1;
for (int i =0; i < m; ++i) h = (h * a + s[i] -'a') % mod, pow = (pow * a) % mod;
seen.insert(h);
bool found = false;
for (int i = m; i < n; ++i) {
h = (h * a - (s[i-m] -'a') * pow % mod + mod) % mod;
h = (h + s[i] -'a') % mod;
if (seen.count(h)) { found = true; break; }
seen.insert(h);
}
if (found) ans = m, l = m +1;
else r = m -1;
}
return ans;
}
};
classSolution {
publicintlongestRepeatingSubstring(String s) {
int n = s.length(), l = 1, r = n, ans = 0;
while (l <= r) {
int m = (l + r) / 2;
Set<Long> seen =new HashSet<>();
long h = 0, a = 26, mod = 1000000007, pow = 1;
for (int i = 0; i < m; ++i) {
h = (h * a + s.charAt(i) -'a') % mod;
pow = (pow * a) % mod;
}
seen.add(h);
boolean found =false;
for (int i = m; i < n; ++i) {
h = (h * a - (s.charAt(i-m) -'a') * pow % mod + mod) % mod;
h = (h + s.charAt(i) -'a') % mod;
if (seen.contains(h)) { found =true; break; }
seen.add(h);
}
if (found) { ans = m; l = m + 1; }
else r = m - 1;
}
return ans;
}
}
classSolution {
funlongestRepeatingSubstring(s: String): Int {
val n = s.length
var l = 1var r = n
var ans = 0while (l <= r) {
val m = (l + r) / 2val seen = mutableSetOf<Long>()
var h = 0Lval a = 26Lval mod = 1_000_000_007L
var pow = 1Lfor (i in0 until m) {
h = (h * a + (s[i] - 'a')) % mod
pow = (pow * a) % mod
}
seen.add(h)
var found = falsefor (i in m until n) {
h = (h * a - (s[i-m] - 'a') * pow % mod + mod) % mod
h = (h + (s[i] - 'a')) % mod
if (h in seen) { found = true; break }
seen.add(h)
}
if (found) {
ans = m
l = m + 1 } else {
r = m - 1 }
}
return ans
}
}
classSolution:
deflongestRepeatingSubstring(self, s: str) -> int:
n = len(s)
l, r, ans =1, n, 0 a, mod =26, 10**9+7while l <= r:
m = (l + r) //2 h, pow_a =0, 1 seen = set()
for i in range(m):
h = (h * a + ord(s[i]) - ord('a')) % mod
pow_a = (pow_a * a) % mod
seen.add(h)
found =Falsefor i in range(m, n):
h = (h * a - (ord(s[i-m]) - ord('a')) * pow_a % mod + mod) % mod
h = (h + ord(s[i]) - ord('a')) % mod
if h in seen:
found =Truebreak seen.add(h)
if found:
ans = m
l = m +1else:
r = m -1return ans
impl Solution {
pubfnlongest_repeating_substring(s: String) -> i32 {
let n = s.len();
let s = s.as_bytes();
let (mut l, mut r, mut ans) = (1, n, 0);
while l <= r {
let m = (l + r) /2;
letmut seen = std::collections::HashSet::new();
let (mut h, a, mod_, mut pow) = (0u64, 26u64, 1_000_000_007u64, 1u64);
for i in0..m {
h = (h * a + (s[i] -b'a') asu64) % mod_;
pow = (pow * a) % mod_;
}
seen.insert(h);
letmut found =false;
for i in m..n {
h = (h * a + (s[i] -b'a') asu64) % mod_;
h = (h + mod_ - ((s[i-m] -b'a') asu64* pow % mod_)) % mod_;
if seen.contains(&h) {
found =true;
break;
}
seen.insert(h);
}
if found {
ans = m;
l = m +1;
} else {
r = m -1;
}
}
ans asi32 }
}