字符串hash是指将一个字符串s映射为一个,使得该整数可以尽可能唯一的代表也就是唯一标识。换言之,如果两个字符的hash值相同那么我们可以认为两者相同。
这里使用的hash策略,便是把一个字符串的每一位赋予权值
假设都是大写的英文字母。
我们设
H[i]代表前i个hash值
那么
H[i]=H[i−1]∗p+val[i]
这里因为是大写英文字母,只有26 中不同的表示,所以这里可以设p为26。(实际上就是把26进制数用10进制数表示)
接下的问题是如果字符串的位数很长,那么很可能所产生的hash值会超过技术表示的范围(以int和long类型为例)。
所以我们可以设置一个数mod,即去余
H[i]=(H[i−1]∗p+val[i]%mod
那么这样可以解决数字太大的问题,但是会造成的另一个问题是产生碰撞,即不同的字符串的hash值可能会相同。
根据相关资料,如果我们把
p
设置为一个
后来我问斌爷,斌爷说把p设为233就够啦,基本上碰撞的概率极小233。
一个延伸问题:如果我得到了一个字符串的hash值,那么怎么得到其中任意一个子串的hash?
首先易知:
H[i...j]=val[i]∗pj−i+val[i+1]∗pj−i−1+val[i+2]∗pj−i−2+...+val[j]∗p0
显然:
H[j]=H[i−1]∗pj−i+1+H[i...j]
所以:
H[i...j]=(H[j]−H[i−1]∗pj−i+1)
这个时候去模:
H[i...j]=((H[j]−H[i−1]∗pj−i+1)%mod+mod)%mod
完毕。