\(\text{Hash}\)原理
散列表(\(\text{Hash Table}\),也叫哈希表),是根据关键码值(\(Key~value\))直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。
若关键码值为 \(k\),则其值存放在 \(f(k)\) 的存储位置上。由此,不需比较便可直接取得所查记录。其中这个对应关系 \(f()\) 叫做 散列函数。
对不同的关键字可能得到统一散列地址,即 \(k_1 \ne k_2\),而 \(f(k_1) = f(k_2)\),这种现象称为碰撞(冲突)。
字符串\(Hash\)
算法梗概
用以快速判断两个字符串是否相等。
\(hash[1 \dots i]\)表示字符串中首字符到第 \(i\)个字符的哈希值。
其中:
- \(k\) 可以取字符串元素种类,但更常取 \(31,~131\)等特殊数字。
- \(p\) 取较大的质数,保证取模后的解集合的规模尽量的大。
也可以直接用unsigned
型来存储,看作对 \(2^{32}\) 或 \(2^{64}\) 取模,采用这种自然溢出方法的 \(\text{Hash}\),已经证明可以被特殊构造的字符串卡掉。
如果不放心的话可以多取几个大的质数分别取模判断,二次或多次 \(\text{Hash}\)。
性质
设 \(k\) 进制,对 \(p\) 取模,则有:
即:
由此也可推出字符串从第\(i\)项到第\(j\)项的\(hash\)值为:
那么如果我们已知\(hash[i \dots t] (i<t<j)\)和 \(hash[t+1 \dots j]\),该如何求出\(hash[i \dots j]\)呢?(即字符串的合并)
处理完合并,在已知\(hash[1 \dots j]\)和 \(hash[1 \dots i-1]~(2<i<j)\)的情况下,又应该怎样求出\(hash[i \dots j]\)呢?(即字符串的拆分)
已知两端字符长度与 \(hash\) 值,可以进行快速的合并。
已知前缀 \(hash\) 值,可以快速求出区间 \(hash\) 值。