Loading

笔记 字符串哈希

(2023.11.02 第一次发布于洛谷博客)

大概也就是抄了个简洁版。

文前给大家找点乐子:

西江月·证明

即得易见平凡,仿照上例显然。留作习题答案略,读者自证不难。

反之亦然同理,推论自然成立。略去过程Q.E.D.,由上可知证毕。

什么是哈希

文艺一点的说法: 哈希表又称散列表,一种以「key-value」形式存储数据的数据结构。所谓以「key-value」形式存储数据,是指任意的键值 key 都唯一对应到内存中的某个位置。只需要输入查找的键值,就可以快速地找到其对应的 value。可以把哈希表理解为一种高级的数组,这种数组的下标可以是很大的整数,浮点数,字符串甚至结构体。by OI-Wiki

简单来说: 也就是你使用 std::map 实现的功能。

如何构造哈希

一个例子:将字符串视为一个 \(26\) 进制的数,即 a~z 视为 1~26

选取两个互质的数 \(b\)\(h\ (b\lt h)\),其中 \(b\) 为基数,\(h\) 为模数。为了降低冲突概率,\(h\) 要求尽量大,一般来说 \(b=131\)\(13331,h=2^{64}\)

\(h=2^{64}\) 时,取模操作可以利用 unsigned long long 类型的自然溢出完成。

假定字符串 \(C=c_1c_2c_3\dots c_m\),则哈希函数为:

\(H(C)=(c_1\times b^{m-1}+c_2\times b^{m-2}+\dots+c_m\times b^0)\)

滚动哈希优化

用于在 \(O(1)\) 时间复杂度下取出子串 \([l,r]\) 的 hash 值。

\(H(k)\) 为字符串 \(C\)\(k\) 个字符构成字串的哈希值,显然有:

\(H(k)=H(k-1)\times b+c_{k}\)(这个似乎更像人话)

那么可得:

\(H(r)=c_1\times b^{r-1}+\dots+c_{l-1}\times b^{r-l-1}+\color{blue}c_l\times b_{r-l}+\dots+c_r\times b^0\)

\(H(l-1)=c_1\times b^{l-2}+\dots+c_{l-1}\times b^0\)

那么借鉴前缀和的思路,则有:

\(H(l,r)=H(r)-H(l-1)\times b^{r-l+1}\)

时间复杂度 \(O(n+m)\)

posted @ 2024-08-22 19:12  Merlin_Meow  阅读(39)  评论(0)    收藏  举报
Sakana Widget 自定义角色自适应示例