leetcode2156. 查找给定哈希值的子串 反向滑动窗口

leetcode2156

重点为反向滑动窗口和取余后的操作

题意:给你一个字符串s,只包含小写字母,a的值为1依次递增,从其中的长度为k的子串通过hash(s, p, m) = (val(s[0]) * p0 + val(s[1]) * p1 + ... + val(s[k-1]) * pk-1) mod公式得到值为val,若val==hashValue,则这个子串符合条件,若有多个子串则输出第一个符合条件的子串
思路:首先看一眼范围字符串的长度子串长度为2*104,时间复杂度最多能到O(nlogn),power和mod为109,有可能要用到矩阵快速幂。
暴力做法为枚举,显然会超过时间复杂度为O(n2)
然后想到滑动窗口,每次移动一个格子,去头加尾,依次进行则复杂度为O(n),可以尝试,发现不知道怎么去头和加尾,因为你去头的话,后面的数都要除以power,如果是正常的没有mod当然可以,但是mod之后就会有偏差,这种方法行不通。
之后想到反向滑动窗口,去尾加头,去尾除去power不行,但是我可以乘上power,这样就不会产生偏差,加头就直接相加即可。
有以下公式
(a*b)%mod = ((a%mod)*(b%mod))%mod
(a+b)%mod = ((a%mod)+(b%mod))%mod
代码如下:

class Solution {
public:
    string subStrHash(string s, int power, int mod, int k, int hashValue) {
        int n = s.length(), pos = -1;
        long long val = 0, p = 1;
        for(int i = n-1; i > n-k; i--){
            val  = power*(val+s[i]-96)%mod;
            p = p*power%mod;
        }
        for(int i = n-k; i >= 0; i--){
            val = (val+s[i]-96)%mod;  // 加头
            if(val==hashValue) pos = i;
            val = power*(val+mod-p*(s[i+k-1]-96)%mod)%mod; // 去尾
        }
        return s.substr(pos, k);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值