字符串哈希
字符串主要操作:匹配,比较,子串
为了加快匹配速度,用一个哈希函数将一个字符串映射为一个哈希值
进制哈希
将字符串看成b进制数,哈希过程就是将这个b进制数转化为十进制数
\[hash(s)=\sum_{i=0}^{n}{s[i]}\times{base^{l-i-1}}\mod{M}
\]
base:进制,比最大的字符大M:模数,比base大的一个素数l:字符串长度i:下标,从0开始存
求前缀子串哈希
hash[i]表示从下标0到下标i的前缀子串对应的哈希值
i=0,\(hash[0]=s[0]\)
i>0,\(hash[i]=hash[i-1]\times{base}+s[i]\)
求所有前缀子串哈希时间复杂度O(N)
求任意子串哈希
滚动哈希
对于右端下标为r,左端下标为l的子串:
\(h=hash[r]-hash[l-1]\times{base^{r-l+1}}\)
一个长度为N的字符串的子串个数为\(N\times{(N-1)}/2\)
求所有子串哈希时间复杂度\(O(N^2)\)
降低哈希碰撞
将b和M取大
若不取模数,一个字符和一个哈希值一一对应,但哈希值范围可能很大
b和M越大,值域越大,冲突的可能性越小
M最大可以取unsigned long long的大小,也就是\(2^{64}\),可以直接用unsigned long long来存哈希值,溢出数据范围时保留低位,相当于取余,不用取M了(自然溢出)
b/M的选择:27,131,19260817,19660813
M比b要大
双hash
一个字符串取两对不同的b和M,求两次哈希值,两个哈希值组成一个二元组,匹配时需要比较两个哈希值
子串匹配
给定连个字符串s1,s2,求s2是否是s1的子串,和s2在s1中出现频度
- 先求
s2的哈希值 - 求出
s1中所有长度为s2.length()的子串的哈希值,与s2的哈希值比较,相等计数就加一
时间复杂度O(\(L_{1}\))

浙公网安备 33010602011771号