题意:
给出一个字符串 S,考虑其所有重复子串(S 的连续子串,出现两次或多次,可能会有重叠)。
返回任何具有最长可能长度的重复子串。(如果 S 不含重复子串,那么答案为 ""。)
数据范围:
2 <= S.length <= 10^5
S 由小写英文字母组成。
解法:
哈希预处理,
二分长度mid,用map存所有长度为mid的子串的哈希值出现的次数,
判断出现次数是否>=2即可check。
code:
string res;
const int maxm=1e5+5;
const int p=131;
#define ull unsigned long long
ull h[maxm];
ull base[maxm];
int n;
ull ask(int l,int r){
return h[r]-base[r-l+1]*h[l-1];
}
class Solution {
public:
bool check(int mid,string s){
if(!mid)return 1;
map<ull,int>mp;
for(int i=mid;i<=n;i++){
ull t=ask(i-mid+1,i);
mp[t]++;
if(mp[t]>=2){
res="";
for(int j=i-mid+1;j<=i;j++){
res+=s[j];
}
return 1;
}
}
return 0;
}
string longestDupSubstring(string s) {
n=s.size();
res="";
s="("+s;
base[0]=1;
h[0]=0;
for(int i=1;i<=n;i++){
h[i]=h[i-1]*p+s[i];
base[i]=base[i-1]*p;
}
int l=1,r=n;
int ans=0;
while(l<=r){
int mid=(l+r)/2;
if(check(mid,s)){
ans=mid,l=mid+1;
}else{
r=mid-1;
}
}
return res;
}
};