1044. 最长重复子串

字符串哈希学习

h[i] = h[i-1] * p + s[i];
p[i] = p[i - 1] * p;
hashNum = h[i + len] - h[i] * p[len];

可以用字符串哈希来写

  1. 且仅当两个哈希值溢出程度与 Integer.MAX_VALUE 呈不同的倍数关系时,会产生错误结果(哈希冲突),此时考虑修改 或者采用表示范围更大的 long 来代替 int。

  2. int做乘法发生溢出警告,可以 * 1ll 转换成 足够大的long long 来完成乘法操作,然后强行向下转换int

  3. long long做乘法发生溢出警告,可以转换成足够大的__int128 来完成乘法操作,然后强行向下转换long long

  4. mp.clear();减少哈希冲突

C++ 代码如下

class Solution {
    // 且仅当两个哈希值溢出程度与 Integer.MAX_VALUE 呈不同的倍数关系时,会产生错误结果(哈希冲突),此时考虑修改  或者采用表示范围更大的 long 来代替 int。
    // int做乘法发生溢出警告,可以 * 1ll 转换成 足够大的long long 来完成乘法操作,然后强行向下转换int
    //131 4999 2011
   public:

    long long P = 131313,sz;
    long long h[30010],p[30010];
    unordered_map<long long,int> mp;
    void pre(string & s){
        h[0] = p[0] = 1;
        for(int i = 1; i <= sz; ++i){
            h[i] = ( __int128) h[i- 1] * P + s[i - 1];
            p[i] = ( __int128) p[i - 1] * P; 
        }
    }
    long long get(int i,int len){
        return h[i + len] - ( __int128)h[i] * p[len];
    }
    string longestDupSubstring(string s) {
       
        sz = s.size();
         pre(s);
        string ans = "",y;
        int l = 1,r = sz - 1,m;
        while(l <= r){
            mp.clear();//记得clear减少哈希冲突
            bool f = false;
            m = (l + r) >> 1;
            for(int i = 0; i <= sz - m; ++i){
               
                long long x = get(i,m);
                 
                if(mp.count(x)){
                    f = true;
                    ans = s.substr(i, m);
                    break;
                }else ++mp[x];
            }
            if(f)
                l = m + 1;
            else r = m - 1;
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值