文章目录
- 一. 哈希是什么
- 二.模版
一. 哈希是什么
哈希算法可以看作一种加密过程,是从明文到密文的一种不可逆的加密手段。
当一个字符串规模很大,并且需要多次访问该字符串或者子串的时候,我们可以用哈希对每个字符串进行哈希,分别映射到不同的数字中去,即一个整数哈希值,然后我们可以根据哈希值找到需要的字符串。
unordered_map 底层实现是哈希表,unordered_set 底层实现是哈希表。
求哈希值方法:设定一个进制 P,需要计算一个字符串的哈希值时,把每个字符看成每个进制位上的一个数字,这个串转化成了一个基于进制 P 的数,最后对 M 取余数,就得到了这个字符串的哈希值。
但是我们会发现这个值会很大,一般会取余一个较大的质数来解决,但如果出现两个一样的哈希值就会产生哈希冲突。
那么哈希冲突怎么解决呢,我们无法通过一些方法使冲突的概率降到0,并且题目如果想让你的普通哈希过不了,也十分简单(参考生日悖论),所以我们可以采取双哈希的方法,就是做两次哈希,每次取不同的底数和进制,每次比较比较两次哈希的结果,这样可以大大减低冲突的概率
例:求abc的哈希值
解法 :a对应97,b对应98,c对应值99,因为基于ASCII 码,所以是128进制。
哈希值为:c*128^0+b*128^1+a*128^2=99*1+98*128+97*16384=不想算了。
求一个字符串的哈希:采取递推的方法,先将只有第一位字符的哈希值求出来,而每加上前一位就在前移个哈希值的基础上*128+这一位,再区域,此时最后一位所存的哈希值就是这个字符串的哈希值。
求一段字符串区间的哈希值:
hash[i]表是字符串前i位的哈希值,pw[i]表示128的i次方,mod是取余的数。
公式:(hash[r]-hash[l-1]*pw[r-l+1]%mod+mod)%mod
取余mod再加mod再取余mod是为了防止取余后出现负数。
二、模版
1.求一个字符串的哈希值
代码如下(示例):
has[0]=s[0]%mod;
for(int i=1;i<s.size();i++){
has[i]=(has[i-1]*128+s[i])%mod;
}
cout<<has[s.size()-1];
2.求一段区间的哈希值
代码如下(示例):
(has[r]-has[l-1]*pw[r-l+1]%mod+mod)%mod
三.例题
1.查字典
题意:
若干组数据,每组数据:
第一行包含一个整数n,表示字典条目数量。
然后是行,每行代表一个字典条目,包含一个英语单词,后面是一个空格和一个外语单词。没有一个外语单词在词典中出现超过一次。
接下来一行包含一个整数 m,表示你需要翻译的信息条数。信息是一连串的外语单词,每行一个单词。
输入的每个词都是最多2000个小写字母的非空序列。
题解:比较每一个的哈希值,如果相等输出对应的字符串,否则输出en。
代码:
2.不同字串
题意:
给你一个仅由小写字母组成的长度为 n 的字符串,问你其中有多少个不同的长度为 L 的子串。
第一行两个数 n,L。
第二行一个字符串。
一行一个数,表示答案。
题解方法:双哈希算一遍,如果不相等计数器加1.
代码: