二分+map+字符串hash/后缀自动机——leetcode 最长重复字串

这题显然可以用后缀自动机的endpos集合来做,复杂度也应该是所有解法里最优秀的O(n)

但是写起来太麻烦了,用二分+字符串hash可以轻松过掉

ps:本题hash冲突比较严重,但是用自然溢出反而不会冲突。。另外用unordered_map比map要快很多

class Solution {
public:
    #define ll unsigned long long 
    #define P 13331
    #define N 100005
    ll n,p[N];
    string ans;
    char s[N];
    unordered_map<ll,int>mp;

    int judge(int len){
        mp.clear();
        ll hash=0;
        for(int i=1;i<=len;i++)
            hash=hash*P,hash=hash+s[i]-'a';
        mp[hash]=1;
        for(int i=len+1;i<=n;i++){
            hash=hash-p[len]*(s[i-len]-'a');
            hash=hash*P;
            hash=(hash+s[i]-'a');
            if(mp[hash]>=1){//更新答案
                if(len>ans.size()){
                    ans="";
                    for(int j=i-len+1;j<=i;j++)
                        ans+=s[j];
                }
                return 1;
            }else mp[hash]=1;
        }
        return 0;
    }

    string longestDupSubstring(string S) {
        n=S.size();
        for(int i=0;i<n;i++)s[i+1]=S[i];
        p[1]=1;
        for(int i=2;i<=n;i++)p[i]=p[i-1]*P;
        
        int L=1,R=n-1,mid;
        ans="";
        while(L<=R){
            mid=L+R>>1;
            if(judge(mid))
                L=mid+1;
            else R=mid-1;
        }
        return ans;
    }
};
原文地址:https://www.cnblogs.com/zsben991126/p/13153646.html