浅谈哈希hash
哈希表
哈希表其实就是建立和存储一种映射关系
离散化、桶排序就是一种简单数值哈希
常见的哈希方法:
除法哈希法 hash(key)=keymod M(M为素数)
乘法哈希法 hash(key)=floor(M/W*(a*key mod W))
通常设置M为2的幂次方
W为计算机字长大小(也为2的幂次方)
a为一个非常接近于W的数
若a=W*(√5-1)/2,则为斐波拉契哈希法
相同的输入hash之后一定相同hash值相同的值一定是同一个输入吗?
—— “哈希冲突”
哈希冲突
是哈希就会冲突,但是合理的选择哈希函数可以让冲突的概率降低真的冲突了怎么办?
冲突解决办法:
拉链法 链表实现,每个位置一个链表,存储冲突的元素
开放地址法 如果冲突,就按一定的规则放到其它位置
字符串哈希
OI里面常常涉及到的时候字符串哈希,字符串哈希的算法也有很多
最著名的就是BKDR Hash具体做法:
•将字符串变成数值,并且最后变成的数值是一个P进制的数(一般取131或者13331)一般来说P最好为素数.
•由于字符串相同,就转化为区间的值相同,所以求一个前缀和
构造方法:
假如给你一个数字1166,形式上你只知道它只是1和6的组合
但你知道它代表的实际大小1103+1102+6101+6100
同理,给你一个字符串,要把它转换为数字
就可以先把每一个字符都先对应一个数字
然后把它们按照顺序乘以进制的幂进行相加
算法过程
处理过程
•把字符串看成P进制数
•预处理字符串所有的前缀hash值hash[i] = (hash[i-1] * P + str[i])mod Q
•计算区间hash值hash[l, r] = hash[r] -hash[l-1] * p[r -l + 1]这里P一般取131或者13331
•Q一般取1e9+7或1e9+9等大素数,这样冲突的机率极小(姑且视作不冲突)
•如果Q取,可以直接用unsigned long long自然溢出反复求值,提前预处理p[n]:更佳
一本通另一种求区间hash值的方法
H[m]=(C1pm-1+C2pm-2+...+Cmp0)% MOD
H[k]=H[k-1]*p+str[k];
举个例子:
C=“ABCD”
H[1]=1;
H[2]=1*p+2;
H[3]=1p2+2p+3;
H[4]=1p3+2p2+3*p+4;
然后对于某一段字符串的哈希值,C'=“BC”
H[C']=H[3]-H[1]*p2
对于C'=Ck+1Ck+2...Ck+n
H[C']=H[k+n]-H[k]*pn
双哈希
为什么要双哈希?
单次哈希判断相同容易被hack,也就是说不同的输入会得到相同的结果,所以建议多次哈希经验证明:其实只需要两次哈希就行了,称为双哈希(要是不放心,三哈希也行,但经过历代older的实践,几乎所有时候双哈希就ok了)
h1[i] = (h1[i]*base1+s[i][j]) % mod1;
h2[i] = (h2[i]*base2+s[i][j]) % mod2;
判断是否相等:h1[i]h1[j]&&h2[i]h2[j]
双哈希参考代码
#include<bits/stdc++.h>
using namespace std;
const int mod1=10000007,mod2=13333337;
int h1[10002], h2[10002];
char s[10002][1502];
int n;
int p1, p2;
int main() {
srand((unsigned)time(0));
p1 = rand()%100+200, p2 = rand()%300+400;
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%s", s[i]);
for(int i=1; i<=n; i++) {
int len=strlen(s[i]);
for(int j=0; j<len; ++j) {
h1[i]=(h1[i]*p1+s[i][j]) % mod1;
h2[i]=(h2[i]*p2+s[i][j]) % mod2;
}
}
int ans= n;
for(int i=1; i<=n; ++i)
for(int j=i-1; j>=1; --j)
if(h1[i]==h1[j] && h2[i]==h2[j] ) {
--ans;
break;
}
printf("%d",ans);
return 0;
}
STL:map
在STL里也有一个类似于哈希一样的key-value对应的东西
map
定义:map<key类型,value类型> namemap
使用了拉链法的哈希表,可以自定义哈希函数(默认有一个哈希函数)
本文作者:Yvette的博客
本文链接:https://www.cnblogs.com/yvette1217/p/16348974.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步