Skip to content

Files

Latest commit

fa73a73 · Jan 16, 2024

History

History

2156.Find Substring With Given Hash Value

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Jan 16, 2024
Jan 16, 2024
Jun 29, 2022

English Version

题目描述

给定整数 p 和 m ,一个长度为 k 且下标从 0 开始的字符串 s 的哈希值按照如下函数计算:

  • hash(s, p, m) = (val(s[0]) * p0 + val(s[1]) * p1 + ... + val(s[k-1]) * pk-1) mod m.

其中 val(s[i]) 表示 s[i] 在字母表中的下标,从 val('a') = 1 到 val('z') = 26 。

给你一个字符串 s 和整数 powermodulok 和 hashValue 。请你返回 s 中 第一个 长度为 k 的 子串 sub ,满足 hash(sub, power, modulo) == hashValue 。

测试数据保证一定 存在 至少一个这样的子串。

子串 定义为一个字符串中连续非空字符组成的序列。

 

示例 1:

输入:s = "leetcode", power = 7, modulo = 20, k = 2, hashValue = 0
输出:"ee"
解释:"ee" 的哈希值为 hash("ee", 7, 20) = (5 * 1 + 5 * 7) mod 20 = 40 mod 20 = 0 。
"ee" 是长度为 2 的第一个哈希值为 0 的子串,所以我们返回 "ee" 。

示例 2:

输入:s = "fbxzaad", power = 31, modulo = 100, k = 3, hashValue = 32
输出:"fbx"
解释:"fbx" 的哈希值为 hash("fbx", 31, 100) = (6 * 1 + 2 * 31 + 24 * 312) mod 100 = 23132 mod 100 = 32 。
"bxz" 的哈希值为 hash("bxz", 31, 100) = (2 * 1 + 24 * 31 + 26 * 312) mod 100 = 25732 mod 100 = 32 。
"fbx" 是长度为 3 的第一个哈希值为 32 的子串,所以我们返回 "fbx" 。
注意,"bxz" 的哈希值也为 32 ,但是它在字符串中比 "fbx" 更晚出现。

 

提示:

  • 1 <= k <= s.length <= 2 * 104
  • 1 <= power, modulo <= 109
  • 0 <= hashValue < modulo
  • s 只包含小写英文字母。
  • 测试数据保证一定 存在 满足条件的子串。

解法

方法一

/**
 * @param {string} s
 * @param {number} power
 * @param {number} modulo
 * @param {number} k
 * @param {number} hashValue
 * @return {string}
 */
var subStrHash = function (s, power, modulo, k, hashValue) {
    power = BigInt(power);
    modulo = BigInt(modulo);
    hashValue = BigInt(hashValue);
    const n = s.length;
    let pk = 1n;
    let ac = 0n;
    // 倒序滑动窗口
    for (let i = n - 1; i > n - 1 - k; i--) {
        ac = (ac * power + getCode(s, i)) % modulo;
        pk = (pk * power) % modulo;
    }
    let ans = -1;
    if (ac == hashValue) {
        ans = n - k;
    }
    for (let i = n - 1 - k; i >= 0; i--) {
        let pre = (getCode(s, i + k) * pk) % modulo;
        ac = (ac * power + getCode(s, i) - pre + modulo) % modulo;
        if (ac == hashValue) {
            ans = i;
        }
    }
    return ans == -1 ? '' : s.substring(ans, ans + k);
};

function getCode(str, index) {
    return BigInt(str.charCodeAt(index) - 'a'.charCodeAt(0) + 1);
}