文章目录
字符串Hash入门
字符串Hash可以通俗的理解为,把一个字符串转换为一个整数。
如果我们通过某种方法,将字符串转换为一个整数,就可以便的确定某个字符串是否重复出现过,这是最简单的字符串Hash应用情景了。
当然也不难想到,如果有不同的两个字符串同时Hash到一个整数,这样就比较麻烦了。我们希望这个映射是一个单射,所以问题就是如何构造这个Hash函数,使得他们成为一个单射。不用担心,接下来的内容正要讲解。
Hash方法
给定一个字符串 S = s 1 s 2 s 3 . . s n S = s_1s_2s_3..s_n S=s1s2s3..sn,对字母x,我们规定 i d x ( x ) = x − ′ a ′ + 1 idx(x) = x - 'a' +1 idx(x)=x−′a′+1。 (当然也可以直接用 s i s_i si的 A S C I I ASCII ASCII值)
自然溢出方法
Hash公式
unsigned long long Hash[n]
h a s h [ i ] = h a s h [ i − 1 ] ∗ p + i d ( s [ i ] ) hash[i] = hash[i-1] * p + id(s[i]) hash[i]=hash[i−1]∗p+id(s[i])
利用unsigned long long的范围自然溢出,相当于自动对 2 64 − 1 2^{64} -1 264−1取模
单Hash方法
Hash公式
h a s h [ i ] = ( h a s h [ i − 1 ] ) ∗ p + i d x ( s [ i ] ) % m o d hash[i] = (hash[i-1]) * p + idx(s[i]) \ \% \ mod hash[i]=(hash[i−1])∗p+idx(s[i]) % mod
其中 p p p和 m o d mod mod均为质数,且有 p < m o d p < mod p<mod。
对于此种Hash方法,将p和mod尽量取大即可,这种情况下,冲突的概率是很低的。
举例
如取 p = 13 , m o d = 101 p = 13, mod = 101 p=13,mod=101,对字符串 a b c abc abc进行Hash
hash[0] = 1
hash[1] = (hash[0] * 13 + 2) % 101 = 15
hash[2] = (hash[1] * 13 + 3) % 101 = 97
这样,我们就认为字符串 a b c abc abc当做97,即97就是 a b c abc abc 的hash值。
双Hash方法
将一个字符串用不同的 m o d mod mod hash两次,将这两个结果用一个二元组表示,作为Hash结果。
Hash公式
h a s h 1 [ i ] = ( h a s h 1 [ i − 1 ] ) ∗ p + i d x ( s [ i ] ) % m o d 1 hash1[i] = (hash1[i-1]) * p + idx(s[i]) \ \% \ mod1 hash1[i]=(hash1[i−1])∗p+idx(s[i]) % mod1
h a s h 2 [ i ] = ( h a s h 2 [ i − 1 ] ) ∗ p + i d x ( s [ i ] ) % m o d 2 hash2[i] = (hash2[i-1]) * p + idx(s[i]) \ \% \ mod2 hash2[i]=(hash2[i−1])∗p+idx(s[i]) % mod2
hash结果为 < h a s h 1 [ n ] , h a s h 2 [ n ] > <hash1[n],hash2[n]> <hash1[n],h