hash

在学习bitcoin最开始的论文的时候,关于proof-of-work的部分,有一句话是:

The average work required is exponential in the number of zero bits required and can be verified by executing a single hash.

不是很明白什么是single hash,不知道是单纯的简单的一个hash,还是说的单哈希。。。于是补一下hash。

什么是哈希表?

哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

记录的存储位置=f(关键字)

这里的对应关系f称为散列函数,又称为哈希(Hash函数),采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表或哈希表(Hash table)。

哈希表hashtable(key,value) 就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。(或者:把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。)
而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,就可以充分利用到数组的定位性能进行数据定位。

数组的特点是:寻址容易,插入和删除困难;

而链表的特点是:寻址困难,插入和删除容易。

那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表

单Hash方法

Hash公式

hash[i]=(hash[i−1])∗p+idx(s[i]) % mod

其中p和mod均为质数,且有p<mod。

对于此种Hash方法,将p和mod尽量取大即可,这种情况下,冲突的概率是很低的。

举例

如取p=13,mod=101,对字符串abc进行Hash
hash[0] = 1
hash[1] = (hash[0] * 13 + 2) % 101 = 15
hash[2] = (hash[1] * 13 + 3) % 101 = 97

这样,我们就认为字符串abc当做97,即97就是abc 的hash值。

双Hash方法

将一个字符串用不同的mod
hash两次,将这两个结果用一个二元组表示,作为Hash结果。

Hash公式

hash1[i]=(hash1[i−1])∗p+idx(s[i]) % mod1

hash2[i]=(hash2[i−1])∗p+idx(s[i]) % mod2

hash结果为<hash1[n],hash2[n]>

这种Hash很安全。

获取子串的Hash

如果我们求出一个串的Hash,就可以O(1)求解其子串的Hash值。 我们先以一个具体的例子来理解。

例子

假设有一|S|=5
的字符串,设Si为第i个字符,其中1≤i≤5。

根据定义分别求出hash[i]

hash[1]=s1

hash[2]=s1∗p+s2

hash[3]=s1∗p2+s2∗p+s3

hash[4]=s1∗p3+s2∗p2+s3∗p+s4

hash[5]=s1∗p4+s2∗p3+s3∗p2+s4∗p+s5

现在我们想求s3s4的hash值,不难得出为s3∗p+s4,并且从上面观察,如果看hash[4]−hash[2]并将结果种带有s1,s2系数的项全部消掉,就是所求。但是由于p的阶数,不能直接消掉,所以问题就转化成,将hash[2]乘一个关于p的系数,在做差的时候将多余项消除,从而得到结果。

不难发现,对应项系数只差一个p2,而4 - 3 + 1 = 2(待求hash子串下标相减再加一),这样就不难推导出来此例题的求解式子。

hash[4]−hash[2]∗p4−2+1至此,通过对上例的归纳,可以得出如下的公式。

公式

若已知一个|S|=n的字符串的hash值,hash[i],1≤i≤n,其子串sl…sr,1≤l≤r≤n对应的hash值为:

hash=hash[r]−hash[l−1]∗pr−l+1考虑到hash[i]每次对p取模,进一步得到下面的式子:

hash=(hash[r]−hash[l−1]∗pr−l+1)%MOD

看起来这个式子人畜无害,但是对于取模运算要谨慎再谨慎,注意到括号里面是减法,即有可能是负数,故做如下的修正:

hash=((hash[r]−hash[l−1]∗pr−l+1)%MOD+MOD)%MOD

至此得到求子串hash值公式。

值得一提的是,如果需要反复对子串求解hash值,预处理p的n次方效果更佳。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值