link
class Solution {
public:
const int mod=1E9+7;
vector<long long> powerof26;
string longestDupSubstring(string S) {
int n=S.size();
powerof26.resize(n);
powerof26[1]=26;
for(int i=2;i<n;i++){
powerof26[i]=powerof26[i-1]*26%mod;
}
int left=1;
int right=n-1;
string res="";
while(left<=right){
int mid=left+(right-left)/2;
string ret=find(S,mid);
if(ret!=""){
if(ret.size()>res.size()) res=ret;
left=mid+1;
}else{
right=mid-1;
}
}
return res;
}
string find(string& s, int len){
unordered_map<int,vector<int>> mp;
long long hash=0;
for(int i=0;i<len;i++){
hash=(hash*26+s[i]-'a')%mod;
}
mp[hash].push_back(0);
for(int right=len;right<s.size();right++){
hash=(hash*26+(s[right]-'a'))%mod;
hash=(hash-(s[right-len]-'a')*powerof26[len]%mod+mod)%mod;
if(mp.find(hash)!=mp.end()){
for(int i:mp[hash]){
if(s.substr(i,len)==s.substr(right-len+1,len)){
return s.substr(i,len);
}
}
}
mp[hash].push_back(right-len+1);
}
return "";
}
};