在替换字符串中的单个字符时修改哈希值 (c++)
Modify hash value on replacing a single character in string (c++)
我正在使用多项式哈希函数来计算字符串(仅由小写英文字母组成)的哈希值,如下所示:
int SZ = 105, P = 31;
long long M = 1e12 + 9;
vector <long long> pw;
pw.resize(SZ, 1);
for(int i = 1; i < SZ; i++) {
pw[i] = (pw[i - 1] * P) % M;
}
long long calculateHash(string &s) {
long long h = 0;
for(int i = 0; i < s.length(); i++) {
h = (h + (s[i] - 'a' + 1) * pw[i]) % M;
}
return h;
}
我不想在 O(N) 时间内重新计算整个字符串的散列,因为我必须只替换任何给定位置的一个字符。因此,为了在 O(1) 时间内完成此操作,我执行以下操作:
long long h1 = calculateHash(s1);
long long h2 = calculateHash(s2);
// Only one character differs in `s1` and `s2` at index `idx`
// Modifying hash for h1 to incorporate s2[idx] and removing s1[idx]
h1 = (h1 + ((s2[idx] - s1[idx]) * pw[idx])) % M;
现在我检查h1 == h2
,理想情况下应该是相等的,对吧?它确实适用于较小的字符串,但有时会失败,我得到 h1
的负值,不确定这是溢出问题还是 ((s2[idx] - s1[idx]) * pw[idx])
更负导致 h1 低于零。
任何人都可以建议一种在仅更改一个字符的情况下在 O(1) 时间内重新计算哈希的方法吗?提前致谢!
原则上你改变结果值的想法是正确的,但你需要的是一个模运算符,它的结果总是正的,对于负输入数字也是如此。
要使用 C++ 模模拟此行为,您可以执行以下操作:
long long tmp=(h1 + ((s2[idx] - s1[idx]) * pw[idx])) % M;
h1=(tmp+M)%M;
第一行是你做的相同操作,第二行使结果为正,因为在 C++ 模运算后 tmp
不能小于 -M
。需要额外的模数来确保数字保持小于 M
,即使 tmp
已经是正数。
我正在使用多项式哈希函数来计算字符串(仅由小写英文字母组成)的哈希值,如下所示:
int SZ = 105, P = 31;
long long M = 1e12 + 9;
vector <long long> pw;
pw.resize(SZ, 1);
for(int i = 1; i < SZ; i++) {
pw[i] = (pw[i - 1] * P) % M;
}
long long calculateHash(string &s) {
long long h = 0;
for(int i = 0; i < s.length(); i++) {
h = (h + (s[i] - 'a' + 1) * pw[i]) % M;
}
return h;
}
我不想在 O(N) 时间内重新计算整个字符串的散列,因为我必须只替换任何给定位置的一个字符。因此,为了在 O(1) 时间内完成此操作,我执行以下操作:
long long h1 = calculateHash(s1);
long long h2 = calculateHash(s2);
// Only one character differs in `s1` and `s2` at index `idx`
// Modifying hash for h1 to incorporate s2[idx] and removing s1[idx]
h1 = (h1 + ((s2[idx] - s1[idx]) * pw[idx])) % M;
现在我检查h1 == h2
,理想情况下应该是相等的,对吧?它确实适用于较小的字符串,但有时会失败,我得到 h1
的负值,不确定这是溢出问题还是 ((s2[idx] - s1[idx]) * pw[idx])
更负导致 h1 低于零。
任何人都可以建议一种在仅更改一个字符的情况下在 O(1) 时间内重新计算哈希的方法吗?提前致谢!
原则上你改变结果值的想法是正确的,但你需要的是一个模运算符,它的结果总是正的,对于负输入数字也是如此。
要使用 C++ 模模拟此行为,您可以执行以下操作:
long long tmp=(h1 + ((s2[idx] - s1[idx]) * pw[idx])) % M;
h1=(tmp+M)%M;
第一行是你做的相同操作,第二行使结果为正,因为在 C++ 模运算后 tmp
不能小于 -M
。需要额外的模数来确保数字保持小于 M
,即使 tmp
已经是正数。