字符串哈希

进制哈希

BKDRHash哈希函数

字符串哈希使。但是为了将映射关系一一对应,也就是,一个字符串代表一个数字,那么一个数字也对应一个字符串。
我们希望这一个映射是个单射,即保证任意的字符串对应的数字是唯一的,也就是不出现一个数字对应两个字符串等情况。

BKDRHash
BKDRHash是一种“进制哈希”,计算步骤非常简单。设定一个进制P,需要计算一个字符串的哈希值时,把每个字符看作每个进制位上的一个数字,这个串转换为一个基于进制P的数,最后对M取余数,就得到了这个字符串的哈希值。

注意:
由于得到的哈希值都很大,不能直接映射到一个巨大的空间上,所以一般都需要限制空间。方法是取余,把得到的哈希值对一个设定的空间大小M取余数,以余数作为索引地址。当然这样做可能产生冲突问题。

编程时可以采用一种隐性取余的方法。取空间大小为M=264,64是unsigned long long 型的长度,一个unsigned long long型的哈希值H,当H>M时会自动溢出,等价于自动对M取余,这样可以避免低效的取余运算。

举例子:
以字符串“abc”为例,令进制P=131,有以下两种方法。
1:把每个字符看作一个数字,即a=1,b=2,c=3....z=26,然后把字符串的每位按进制P的权值相加得a1312+b1311+c1310=17426

2.:把每个字符的ASCII码直接看成代表它的数字也可以,计算得a1312+b1311+c1310=1677554

进制P常用的值有31131131313131131313等,用这些数值可以有效避免碰撞。

由于常常会碰到到字符串匹配的题目中,所以验证某两段子串是否相等这个方法很重要

#include <bits/stdc++.h>
using namespace std;
using u64 = unsigned long long;
u64 base = 13331;
vector<u64>p, hx; //p存进制位,hx存当前字符串长度的哈希值
//也可以把hx理解成前缀和数组
void Hash(string &s) {
s = " " + s;
int N = s.size();
p.resize(N + 1), hx.resize(N + 1);
p[0] = 1, hx[0] = 0;
for (int i = 1; i < s.size(); i++) {
p[i] = p[i - 1] * base; //存进制数
hx[i] = hx[i - 1] * base + s[i]; //字符串哈希
}
}
u64 get(int l, int r) { //获取子串的哈希,常用来字符串匹配
return hx[r] - hx[l - 1] * p[r - l + 1];
}
//检查两个子串是否相等
bool same(int l1, int r1, int l2, int r2) {
return get(l1, r1) == get(l2, r2);
}
int main() {
}

模版题P3370 【模板】字符串哈希
理解思想和方法,灵活的选择和调整自己的模板!!!

省赛难题D. Period

posted on   swj2529411658  阅读(10)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示