字符串哈希算法
一、字符串哈希:将一串字符串映射成一个整数,并用它来代替字符串进行比较。这样俩个字符串的比较就变成俩个整数的比较,可以将时间复杂度减少至O(1)
二、哈希函数:为了将字符串转化为整数,需要一个哈希函数hash,使得以下条件成立:如果字符串s == t 那么 hash(s) == hash(t)。一般情况下采用多项式 哈希函数构造:
对于一个长度为n的字符串s的hash值计算:
为了减少哈希冲突,p需要选择一个素数,m需要选择一个足够大的数,因为俩个随机字符串碰撞的概率大约是1/m,这里使
三、实现
long long compute_hash(string const& s) {
const int m = 1e9+7;
const int p = 1333; //如果出现冲突,p需要取更大的素数再测试
long long has_val = 0;
for(char c : s) {
has_val = (has_val*p + c - 'a') % m;
}
return has_val;
}
四、快速计算子字符串哈希
单次计算一个字符串的哈希值复杂度是O(n),其中n为串长度,按照多项式哈希公式,假设子字符串
使用前缀数组
五、应用题目
class Solution {
public:
vector<string> findRepeatedDnaSequences(string s) {
int n = s.size();
vector<long long> p(n+1);
vector<long long> h(n+1);
const int base = 123, mod = 1e+9;//实际测试base=123能过
p[0] = 1;
//构建字符串哈希前缀
for(int i = 1; i <= n; i++) {
h[i] = (h[i-1]*base + s[i-1]) % mod;
p[i] = (p[i-1]*base) % mod;
}
int len = 10;
unordered_map<long long, int> hash_count;
vector<string> ans;
for(int i = 1; i + len - 1 <= n; i++)
{
int j = i + len - 1;
int t = (h[j] - h[i-1]*p[j-i+1]) % mod;
int hash = (t + mod) % mod;
if(hash_count.count(hash) && hash_count[hash] == 1) {
ans.emplace_back(s.substr(i-1, len));
}
hash_count[hash]++;
}
return ans;
}
};
六、哈希冲突和自然溢出
- 第i次进行hash求值的时候,有
的概率不会发生碰撞,由此可以知道M的值越大,越不容易发生冲突 - 自然溢出法:利用了unsigned long long 这一基本类型在溢出的时候对
取模这一性质达到了取模的效果 - 187. 重复的DNA序列 自然溢出解法
class Solution {
public:
vector<string> findRepeatedDnaSequences(string s) {
int n = s.size();
vector<unsigned long long> p(n+1);
vector<unsigned long long> h(n+1);
int base = 13333; //当发生冲突时,选取更大素数尝试
p[0] = 1;
for(int i = 1; i <= n; i++) {
p[i] = p[i-1] * base;
h[i] = h[i-1] * base + s[i-1];
}
unordered_map<unsigned long long, int> hash_count;
vector<string> ans;
int len = 10;
for(int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
unsigned long long hash = h[j] - h[i-1]*p[j-i+1];
if(hash_count.count(hash) && hash_count[hash] == 1) {
ans.emplace_back(s.substr(i-1, len));
}
hash_count[hash]++;
}
return ans;
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?