给出一个字符串 S,考虑其所有重复子串(S 的连续子串,出现两次或多次,可能会有重叠)。
返回任何具有最长可能长度的重复子串。(如果 S 不含重复子串,那么答案为 “”。)
示例 1:
输入:“banana”
输出:“ana”
示例 2:
输入:“abcd”
输出:""
提示:
2 <= S.length <= 10^5
S 由小写英文字母组成。
二分法+滚动哈希 1344ms
class Solution {
public:
const long long mod = LLONG_MAX / 27;
string longestDupSubstring(string S) {
vector<int> p((int)S.length());
for(int i = 0; i < S.length(); ++i)
p[i] = S[i]-'a'+1;
int l = 1, r = (int)S.length()-1, ans = 0, d = 0;
while(l <= r)
{
int mid = (l+r) >> 1;
if (check(p, mid, d))
{
ans = mid;
l = mid+1;
}else r = mid-1;
}
return S.substr(d, ans);
}
bool check(const vector<int> &p, int m, int &d)
{
int n = (int)p.size();
unordered_set<long long> q;
long long t = 0,h=1;
int a=27;
for(int i = 0; i < m; ++i)
{
h = (h*a)%mod;
t = (t*a%mod + p[i])%mod;
}
q.insert(t);
for(int i = m; i < n; ++i)
{
t = ((t*a%mod + p[i])%mod - p[i-m]*h%mod + mod)%mod;
if (q.count(t) > 0)
{
d=i-m+1;
return true;
}
q.insert(t);
}
return false;
}
};