字符串哈希笔记

文章目录

  • 一. 哈希是什么
  • 二.模版

一. 哈希是什么

哈希算法可以看作一种加密过程,是从明文到密文的一种不可逆的加密手段。

当一个字符串规模很大,并且需要多次访问该字符串或者子串的时候,我们可以用哈希对每个字符串进行哈希,分别映射到不同的数字中去,即一个整数哈希值,然后我们可以根据哈希值找到需要的字符串。

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.

代码:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值