最长重复子串
最暴力的方法:
O
(
n
3
)
O(n^3)
O(n3)枚举每种长度、每个起始位置、再用O(n)的开销去检查是否有重复子串。
- 优化1
字符串hash预处理,省去O(n)的开销 - 优化2
枚举长度的时候明显具有单调性,二分处理。
时间复杂度: O ( n ∗ l o g ( n ) ) O(n*log(n)) O(n∗log(n))
这道题的做法也可以套用在最长回文子串上面
typedef unsigned long long ull;
class Solution {
public:
int P = 1e9+7 ,n ;
ull h[100010]={0},p[100010];
string longestDupSubstring(string s) {
n = s.size();
p[0] = 1;
for(int i=1;i<=n;i++){
h[i] = h[i-1]*P+(s[i-1]-'a'+1);
p[i] = p[i-1]*P;
}
int l = 1,r = n-1,maxLen = 0;
string ans = "";
while(l<=r){
int mid = l+(r-l)/2;
string res = isOk(mid,s);
if(res.size()>0){
maxLen = max(maxLen,mid);
ans = res;
l = mid+1;
}else{
r = mid-1;
}
}
return ans;
}
string isOk(int len,const string &s){
unordered_map<ull,int> mp;
string ans = "";
for(int i=1;i<=n;i++){
if(i+len-1<=n){
if( ++mp[ h[i+len-1]-h[i-1]*p[len]] >= 2 ){
ans = s.substr(i-1,len);
break;
}
}
}
return ans;
}
};