2156. Find Substring With Given Hash Value
The hash of a 0-indexed string s of length k, given integers p and m, is computed using the following function:
hash(s, p, m) = (val(s[0]) * p0 + val(s[1]) * p1 + ... + val(s[k-1]) * pk-1) mod m.
Where val(s[i]) represents the index of s[i] in the alphabet from val('a') = 1 to val('z') = 26.
You are given a string s and the integers power, modulo, k, and hashValue. Return sub, the first substring of s of length k such that hash(sub, power, modulo) == hashValue.
The test cases will be generated such that an answer always exists.
A substring is a contiguous non-empty sequence of characters within a string.
Constraints:
1 <= k <= s.length <= 2 * 104
1 <= power, modulo <= 109
0 <= hashValue < modulo
s consists of lowercase English letters only.
The test cases are generated such that an answer always exists.
Analysis
This is question is about rolling hash.
The formula is given, but we cannot use it directly. Or if we scan the string from left to right, the hashValue needs to divide the power, which may give incorrectly hashing result.
To bypass this, we can just scan from right to left. Then no division is needed.
See the code below,
class Solution {
public:
string subStrHash(string s, int power, int modulo, int k, int hashValue) {
int n = s.size(), id = n;
long sum = 0, p = 1;
for(int i=n-1; i>=0; --i) {
if(i>=n-k) p = p*power%modulo; // p = power^k%modulo
sum = (sum*power + (s[i]-'a'+1))%modulo;
if(i<=n-k-1) {
sum = (sum - (s[i+k]-'a'+1)*p%modulo + modulo)%modulo;
}
if(i<=n-k && sum == hashValue) {
cout<<i<<endl;
id = i;
}
}
return id<n ? s.substr(id, k) : "";
}
};
Comments
Post a Comment