leetcode 1044. 最長重復子串(字符串hash)


題意:

給出一個字符串 S,考慮其所有重復子串(S 的連續子串,出現兩次或多次,可能會有重疊)。

返回任何具有最長可能長度的重復子串。(如果 S 不含重復子串,那么答案為 ""。)

 

示例 1:

輸入:"banana"
輸出:"ana"

 

示例 2:

輸入:"abcd"
輸出:""

 

思路:(字符串hash+二分)

針對長度簡單的從length(S)-1遞減時間過長的問題。如果有長度為L的最長重復子串,則必然有L_0<L的重復子串,因此先采用二分法尋找到最長重復子串的長度。

51nod2619也利用了字符串hash

 

 1 typedef unsigned long long ull;
 2 const int N=1e5+10;
 3 const ull base=23333;
 4 class Solution {
 5 public:
 6     ull _hash[N],p[N];
 7     ull get(int l,int r){
 8         return _hash[r]-_hash[l-1]*p[r-l+1];
 9     }
10     void init(string s){
11         p[0]=1;
12         for(int i=1;i<=s.size();i++){
13             p[i]=p[i-1]*base;
14             _hash[i]=_hash[i-1]*base+s[i-1]-'a';
15         }
16     }
17     int check(int mid,int len){
18         unordered_map<ull,bool>mp;
19         for(int i=1;i+mid-1<=len;i++){
20             ull k=get(i,i+mid-1);
21             if(mp.find(k)!=mp.end())return i;
22             mp[k]=true;
23         }
24         return 0;
25     }
26     string longestDupSubstring(string S) {
27         init(S);
28         int len=S.size();
29         string ans="";
30         int l=1,r=len-1;
31         while(l<=r){
32             int mid=(l+r)/2;
33             if(check(mid,len))l=mid+1;
34             else r=mid-1;
35         }
36         l--;
37         if(l==-1)return "";
38         int k=check(l,len);
39         return S.substr(k-1,l);
40     }
41 };
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM