一篇文章看懂字符串哈希
定义
将一个字符串映射至一个整数\(w\)后称\(w\)为该字符串的\(hash\)值。
性质
对于一个固定的字符串,其在使用相同\(hash\)生成方式下得到的\(hash\)值唯一,而且对于每一个固定的\(hash\)值,其所对应的字符串在很大概率下是唯一的,因此我们在求出字符串的\(hash\)值后可以通过判断两字符串\(hash\)值是否相等来快速判断两字符串是否相同(当然是在相同\(hash\)生成方式下)。
生成方式
一、单模数哈希
采用一个数作为\(hash\)模数来进行\(hash\)计算,公式如下:
二、双模数哈希
使用两个模数进行哈希生成,简单地说,就是使用不同的模数(当然,进制也可不同)生成同一个字符串的两组哈希值,公式如下:
三、自然溢出哈希
采用无符号整型进行哈希计算,因为溢出后会自动取模,所以无需使用额外的模数,公式如下:
方式比较:
自然溢出哈希属于单模数哈希的一种,但是不需要手动取模,因此是最方便的一种。
双模数哈希生成两套哈希,可以大大降低冲突概率,安全性高。
单模数哈希一般不被采用,因为真的没什么好处。
模数与进制的选择
模数
一般来说模数选择越大,哈希冲突概率越小,所以一般不用管它,越大越好,而且在使用自然溢出哈希时无需在意(双模数也可以用两个自然溢出出哈希)。
进制
一般对哈希冲突概率影响更大的其实是选择的进制,一般来说,在选择进制时应选择大于当前字符集大小的数,必须是一个奇数,因为在进制选择为偶数的情况下,哈希冲突的发生概率会大大提高。一般来说,进制选择的是一个质数(其实没有必要,纯粹是叠\(buff\))。
对于一个正常的字符串,进制选择的都是\(131\),因为包含了所有可见字符。
子串的\(hash\)值提取
因为\(hash\)基于进制转化,而且它其实是一种类似于前缀和的形式,所以我们其实可以直接进行进制转换进行减法提取,公式如下:
其中\(base_i\)指在\(Base\)进制下第\(i\)位的单位大小。(一般这种提取是在自然溢出哈希下进行,因为它能自动反向溢出,而模数哈希似乎没有这么方便)。
应用
好像所有有字符串的地方都能用,就不多提了。

浙公网安备 33010602011771号