一篇文章看懂字符串哈希

定义

将一个字符串映射至一个整数\(w\)后称\(w\)为该字符串的\(hash\)值。

性质

对于一个固定的字符串,其在使用相同\(hash\)生成方式下得到的\(hash\)值唯一,而且对于每一个固定的\(hash\)值,其所对应的字符串在很大概率下是唯一的,因此我们在求出字符串的\(hash\)值后可以通过判断两字符串\(hash\)值是否相等来快速判断两字符串是否相同(当然是在相同\(hash\)生成方式下)。

生成方式

一、单模数哈希

采用一个数作为\(hash\)模数来进行\(hash\)计算,公式如下:

\[hash[i] = (hash[i - 1] * Base + str[i])\% MOD \]

二、双模数哈希

使用两个模数进行哈希生成,简单地说,就是使用不同的模数(当然,进制也可不同)生成同一个字符串的两组哈希值,公式如下:

\[hash1[i] = (hash1[i - 1] * Base1 + str[i])\%MOD1 \]

\[hash2[i] = (hash2[i - 1] * Base2 + str[i])\%MOD2 \]

三、自然溢出哈希

采用无符号整型进行哈希计算,因为溢出后会自动取模,所以无需使用额外的模数,公式如下:

\[hash[i] = hash[i - 1] * Base + str[i] \]

方式比较:

自然溢出哈希属于单模数哈希的一种,但是不需要手动取模,因此是最方便的一种。

双模数哈希生成两套哈希,可以大大降低冲突概率,安全性高。

单模数哈希一般不被采用,因为真的没什么好处。

模数与进制的选择

模数

一般来说模数选择越大,哈希冲突概率越小,所以一般不用管它,越大越好,而且在使用自然溢出哈希时无需在意(双模数也可以用两个自然溢出出哈希)。

进制

一般对哈希冲突概率影响更大的其实是选择的进制,一般来说,在选择进制时应选择大于当前字符集大小的数,必须是一个奇数,因为在进制选择为偶数的情况下,哈希冲突的发生概率会大大提高。一般来说,进制选择的是一个质数(其实没有必要,纯粹是叠\(buff\))。

对于一个正常的字符串,进制选择的都是\(131\),因为包含了所有可见字符。

子串的\(hash\)值提取

因为\(hash\)基于进制转化,而且它其实是一种类似于前缀和的形式,所以我们其实可以直接进行进制转换进行减法提取,公式如下:

\[\_hash_{l , r} = hash[r] - hash[l - 1] * base[r - l + 1] \]

其中\(base_i\)指在\(Base\)进制下第\(i\)位的单位大小。(一般这种提取是在自然溢出哈希下进行,因为它能自动反向溢出,而模数哈希似乎没有这么方便)。

应用

好像所有有字符串的地方都能用,就不多提了。

完结撒花!!!

posted @ 2024-11-24 21:58  Torrentolf  阅读(444)  评论(0)    收藏  举报