字符串哈希

字符串主要操作:匹配,比较,子串
为了加快匹配速度,用一个哈希函数将一个字符串映射为一个哈希值

进制哈希

将字符串看成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取大

若不取模数,一个字符和一个哈希值一一对应,但哈希值范围可能很大

bM越大,值域越大,冲突的可能性越小
M最大可以取unsigned long long的大小,也就是\(2^{64}\),可以直接用unsigned long long来存哈希值,溢出数据范围时保留低位,相当于取余,不用取M了(自然溢出)

b/M的选择:271311926081719660813
Mb要大

双hash

一个字符串取两对不同的bM,求两次哈希值,两个哈希值组成一个二元组,匹配时需要比较两个哈希值

子串匹配

给定连个字符串s1s2,求s2是否是s1的子串,和s2s1中出现频度

  1. 先求s2的哈希值
  2. 求出s1中所有长度为s2.length()的子串的哈希值,与s2的哈希值比较,相等计数就加一

时间复杂度O(\(L_{1}\))

posted @ 2026-04-18 16:11  mofei1116  阅读(22)  评论(0)    收藏  举报