理论概念
这玩意一直都是个好东西,但是我总觉得玄学的一批。今天借着专题学习的劲头,把Hash好好梳理一下。
定义/作用
哈希这东西应该都不陌生。将复杂的信息映射到一个容易维护的值域之内。那么Hash函数就有点类似于一个映射关系。通过这个函数来产生一个关键值(Key),通过关键值与值(value)的对应关系,制作一个对应表。即哈希表(Hash table)。他可以实现通过Key快速的查找Value。
那么其最大作用也就显而易见。查重。也就是说,查找当前的值是否已经存在。难点在于,如何去产生这个对应关系?简单的映射关系是有相当的可能产生“两组不同的值生成同一个关键值”的错误(我们称其为哈希冲突)。如果哈希函数的设计太水,那么这个哈希冲突也就非常容易产生了。
整数(int)哈希举例
引用了一个对整数数组生成Hash的方法,这里只做举例。在本例中,不关心数组中数的序列问题。即只考虑数组内值不同为不同状态,如果值相同但顺序不同,我们仍认为他是同一状态。(会产生相同的关键值)
对于一组数,其乘积与其累加之和与任意较大质数P取模。
//这里是针对于某一个题目所引入的,所以具体原因会在下方的题目展示中阐释。
字符串哈希
定义与技巧
常用的字符串哈希分两类(没错,我觉得该分两类的!)
自然溢出式Hash与多重Hash。一般来讲,前者虽然发生哈希冲突的几率非常小,但总会被刁钻(诶嘿嘿)的出题人卡几个数据。是的,他们是具备能卡你自然溢出单哈希的能力的。所以稳妥起见,后者运用频率偏高一些。
什么是字符串哈希?就是把一个任意长度的字符串映射成一个非负整数,并且其冲突概率几乎为0
把字符串看作P进制数,并分配一个大于0的数值,代表每种字符。啥意思啊?比如a对应1,b对应2,c对应3。取一个固定的值M,求出该P进制数对于M的余数,作为该字符串的哈希值。一般来说,P取131或者13331,这样冲突几率就极低。一般M取264,也就是一个自然溢出的unsigned long long。就让你溢出,取代低效的取模运算。
这也就是第一类Hash。为了避免被卡,我们多取一些适当的P与M。(例如大质数),进行多组Hash运算。如果结果都相同,我们就认定这是一个相等的字符串。
性质
对没错!我觉得这是性质!!
有了以下两种性质,我们便可以做到在O(N)的时间内预处理所有前缀Hash值,并在O(1)的时间内完成查询任意字串的哈希值。
一、
对于任意新字符串S+C,他的Hash值就是
H(S+C)=(H(S)*P+Value[C])mod M
为什么?我们来进行一个简单的模拟。
例如,S="abc",C=“d”
S表示为P进制的数:1 2 3
H(S)=1*P2+2*P+3
H(S+C)=1*P3+2*P2+3*P+4=H(S)*P+4
这里可以把*P的操作视为在P进制下的左移运算。Value[c]是我们为c选定的代表数值。
二、
如果已知字符串S的Hash值为H(S),字符串S+T的Hash值为H(S+T),那么字符串T的Hash值
H(T)=(H(S+T)-H(S)*Plength(T)) mod M
那么我们继续之前的模拟。
例如,S="abc",C=“d”,T=“xyz”
S表示为P进制的数:1 2 3
S+T的P进制数为:1 2 3 24 25 26
H(S)=1*P2+2*P+3
H(S+T)=1*P5+2*P4+3*P3+24*P2+25*P+26
S在P进制下左移length(T)位:1 2 3 0 0 0
两者相减就是T表示为P进制数:24 25 26
H(T)=H(S+T)-(1*P2+2*P+3)*P3=24*P2+25*P+26
在题目中的Show Time
Snowflake Snow Snowflakes POJ3349
等待补充
兔子与兔子 CH1401
由于目标题库被查表…等待恢复。
好文章 2015模拟题By nodgd
等待补充
原文地址:https://www.cnblogs.com/Uninstalllingyi/p/11191045.html