【字符串】字符串哈希
单哈希
以下是字符串哈希的 C++ 代码模板,基于 多项式滚动哈希 实现,支持快速计算子串哈希值,适用于子串匹配、重复检测等问题:
#include <vector>
#include <string>
using namespace std;
class StringHash {
private:
using LL = long long;
vector<LL> prefix; // 前缀哈希数组
vector<LL> power; // 存储 base 的幂次
LL base, mod; // 哈希参数(基数,模数)
public:
// 初始化哈希参数,可自定义 base 和 mod
explicit StringHash(const string& s, LL base = 131, LL mod = 1e9 + 7)
: base(base), mod(mod) {
int n = s.size();
prefix.resize(n + 1);
power.resize(n + 1);
power[0] = 1; // base^0 = 1
// 预处理前缀哈希和幂次数组
for (int i = 0; i < n; ++i) {
prefix[i + 1] = (prefix[i] * base % mod + s[i]) % mod;
power[i + 1] = power[i] * base % mod;
}
}
// 计算子串 s[left..right] 的哈希值(闭区间,0-based)
LL getHash(int left, int right) {
// 公式:hash = (prefix[right+1] - prefix[left] * power[right-left+1]) % mod
LL res = (prefix[right + 1] - prefix[left] * power[right - left + 1] % mod) % mod;
return res < 0 ? res + mod : res; // 保证结果非负
}
};
/* 使用示例 */
int main() {
string s = "abcde";
StringHash sh(s); // 默认参数 base=131, mod=1e9+7
// 计算 "bc" 的哈希值(对应闭区间 [1,2])
LL hash_bc = sh.getHash(1, 2);
return 0;
}


自然溢出法
class NaturalStringHash {
private:
using ULL = unsigned long long;
vector<ULL> prefix, power;
ULL base;
public:
NaturalStringHash(const string& s, ULL base = 131) : base(base) {
int n = s.size();
prefix.resize(n + 1);
power.resize(n + 1);
power[0] = 1;
for (int i = 0; i < n; ++i) {
prefix[i + 1] = prefix[i] * base + s[i];
power[i + 1] = power[i] * base;
}
}
ULL getHash(int left, int right) {
return prefix[right + 1] - prefix[left] * power[right - left + 1];
}
};

双哈希
以下是双哈希模板的 C++ 实现,通过组合两组不同的哈希参数来降低哈希冲突的概率
#include <iostream>
#include <vector>
#include <string>
using namespace std;
using LL = long long;
class DoubleHash {
private:
struct SingleHash {
vector<LL> prefix, power;
LL base, mod;
// 单个哈希的初始化
SingleHash(const string& s, LL base, LL mod) : base(base), mod(mod) {
int n = s.size();
prefix.resize(n + 1);
power.resize(n + 1);
power[0] = 1;
for (int i = 0; i < n; ++i) {
prefix[i + 1] = (prefix[i] * base % mod + s[i]) % mod;
power[i + 1] = (power[i] * base) % mod;
}
}
// 获取单个哈希值
LL get(int l, int r) {
LL res = (prefix[r + 1] - prefix[l] * power[r - l + 1] % mod) % mod;
return res < 0 ? res + mod : res;
}
};
// 使用两组不同的 base 和 mod 参数
SingleHash h1, h2;
public:
// 构造函数(可自定义参数)
explicit DoubleHash(const string& s,
LL base1 = 131, LL mod1 = 1e9 + 7,
LL base2 = 13331, LL mod2 = 1e18 + 3)
: h1(s, base1, mod1), h2(s, base2, mod2) {}
// 返回双哈希值(pair形式)
pair<LL, LL> get(int l, int r) {
return {h1.get(l, r), h2.get(l, r)};
}
};
/* 使用示例 */
int main() {
string s = "abcabc";
DoubleHash dh(s);
// 计算子串 [0, 2]("abc")的双哈希
auto hash1 = dh.get(0, 2);
// 计算子串 [3, 5]("abc")的双哈希
auto hash2 = dh.get(3, 5);
// 当且仅当两个哈希值都相等时,认为子串相同
if (hash1 == hash2) {
// 两个子串匹配成功
}
return 0;
}


浙公网安备 33010602011771号