classSolution{public:stringlongestDupSubstring(strings){constexprintkMod=1'000'000'007;constintn=s.length();vector<int>pows(n,1);intbestStart=-1;intl=1;intr=n;for(inti=1;i<n;++i)pows[i]=(pows[i-1]*26L)%kMod;while(l<r){constintm=(l+r)/2;constintstart=getStart(s,m,pows,kMod);if(start==-1){r=m;}else{bestStart=start;l=m+1;}}if(bestStart==-1)return"";if(getStart(s,l,pows,kMod)==-1)returns.substr(bestStart,l-1);returns.substr(bestStart,l);}private:// K := length of hashed substringintgetStart(conststring&s,intk,constvector<int>&pows,constint&kMod){unordered_map<int,vector<int>>hashedToStarts;longlongh=0;// Compute hash value of s[:k]for(inti=0;i<k;++i)h=((h*26)%kMod+val(s[i]))%kMod;hashedToStarts[h].push_back(0);// Compute rolling hash by Rabin Karpfor(inti=k;i<s.length();++i){constintstartIndex=i-k+1;h=((h-static_cast<longlong>(pows[k-1])*val(s[i-k]))%kMod+kMod)%kMod;h=(h*26+val(s[i]))%kMod;if(hashedToStarts.count(h)){conststringcurrSub=s.substr(startIndex,k);for(constintstart:hashedToStarts[h])if(s.substr(start,k)==currSub)returnstartIndex;}hashedToStarts[h].push_back(startIndex);}return-1;}intval(charc){returnc-'a';}};
classSolution{publicStringlongestDupSubstring(Strings){finalintkMod=1_000_000_007;finalintn=s.length();int[]pows=newint[n];intbestStart=-1;intl=1;intr=n;pows[0]=1;for(inti=1;i<n;++i)pows[i]=(int)((pows[i-1]*26L)%(long)kMod);while(l<r){finalintm=(l+r)/2;finalintstart=getStart(s,m,pows,kMod);if(start==-1){r=m;}else{bestStart=start;l=m+1;}}if(bestStart==-1)return"";if(getStart(s,l,pows,kMod)==-1)returns.substring(bestStart,bestStart+l-1);returns.substring(bestStart,bestStart+l);}// K := length of hashed substringprivateintgetStart(finalStrings,intk,int[]pows,intkMod){Map<Long,List<Integer>>hashedToStarts=newHashMap<>();longh=0;// Compute hash value of s[:k]for(inti=0;i<k;++i)h=((h*26)%kMod+val(s.charAt(i)))%kMod;hashedToStarts.put(h,newArrayList<>());hashedToStarts.get(h).add(0);// Compute rolling hash by Rabin Karpfor(inti=k;i<s.length();++i){finalintstartIndex=i-k+1;h=((h-(long)(pows[k-1])*val(s.charAt(i-k)))%kMod+kMod)%kMod;h=(h*26+val(s.charAt(i)))%kMod;if(hashedToStarts.containsKey(h)){finalStringcurrSub=s.substring(startIndex,startIndex+k);for(finalintstart:hashedToStarts.get(h))if(s.substring(start,start+k).equals(currSub))returnstartIndex;}hashedToStarts.put(h,newArrayList<>());hashedToStarts.get(h).add(startIndex);}return-1;}privateintval(charc){returnc-'a';}}
classSolution:deflongestDupSubstring(self,s:str)->str:kMod=1_000_000_007bestStart=-1l=1r=len(s)defval(c:str)->int:returnord(c)-ord('a')# K := length of hashed substringdefgetStart(k:int)->Optional[int]:maxPow=pow(26,k-1,kMod)hashedToStart=defaultdict(list)h=0# Compute hash value of s[:k]foriinrange(k):h=(h*26+val(s[i]))%kModhashedToStart[h].append(0)# Compute rolling hash by Rabin Karpforiinrange(k,len(s)):startIndex=i-k+1h=(h-maxPow*val(s[i-k]))%kModh=(h*26+val(s[i]))%kModifhinhashedToStart:currSub=s[startIndex:startIndex+k]forstartinhashedToStart[h]:ifs[start:start+k]==currSub:returnstartIndexhashedToStart[h].append(startIndex)whilel<r:m=(l+r)//2start:Optional[int]=getStart(m)ifstart:bestStart=startl=m+1else:r=mifbestStart==-1:return''ifgetStart(l):returns[bestStart:bestStart+l]returns[bestStart:bestStart+l-1]