[学习笔记 #5] 哈希

[学习笔记 #5] 哈希

下面 [ ] 起来的是我还不确定的。

前言

从今年暑假到现在(2024.11.13),考了多少道哈希,我一道都没场切。前年 CSP-S T3 星战没想出哈希做法,去年 CSP-S T2 又没想出哈希做法。满满的黑历史……

早就想总结了,没时间。今天忍不住了。

哈希表

  • 哈希表和下面说的哈希应该不是一回事。
  • 概括:缩小范围。可以用来存储哈希值。
  • 具体实现:
    • 当集合 \(A\) 较大时,用一个函数 \(f : A \rightarrow B\)\(A\) [映射] 到一个较小的集合 \(B\)
    • 查找时给出 \(B\) 中的元素,对应回 \(A\) 中的元素。
    • 但是 \(B\) 中的一个元素可能对应 \(A\) 中的多个元素,即哈希冲突(或称哈希碰撞)。
      • 两种解决方法:
        1. \(B\) 中的每个元素挂一串(\(A\) 中的)元素。查找时遍历这一串。
        2. \(B\) 中的每个元素只对应一个(\(A\) 中的)元素。那么每添加一个(\(A\) 中的)元素时,如果对应的(\(B\) 中)元素没有对应元素,就对应上,否则接着找,直到找到一个还没对应的,对应上。
  • 实际使用:
    • 可以用 map 或 unordered_map。map 带 \(\log\),但 unordered_map [[可能会被卡]]。
    • 可以用 pb_ds 里的哈希表。

过渡:用哈希解决判定性问题

  • 接下来的哈希用于解决 判定性问题
  • 采用哈希的原因:常规方式难以判定。
  • 方法:
    • 我们找 充分条件或必要条件(不是充要条件) 来判定,使用哈希来简化问题。
    • 通过随机和多次判定来降低错误概率。
    • 可以从原命题或 [[原命题的否定]] 两方面考虑。
    • 判断是否是某种情况,就要先选择哈希的方式(要有针对性),再得到这样哈希的话这种情况的值是多少或是什么情况,最后判断真实的哈希值是否满足条件。

不知道归到哪里去的技巧

  • 四次方([可能] 要取模)。[使哈希值更离散。]
  • 双哈希。
  • 多次哈希。

集合哈希

  • 通过运算的交换律来 [表现] 集合的 [无序性]。

  • 可以转化为序列哈希:

    • 方法一:

      • 对集合中每个值,记录它的出现次数,记到一个序列(桶)上(给值固定了顺序)。
        • 可重集:就是这样。
        • 不是可重集:出现次数是 \(0\)\(1\)
      • 对这个序列跑序列哈希。
    • 方法二:

      • 对集合排序(规定某种顺序,不一定从小到大),跑序列哈希。

Sum Hashing

  • 哈希值表示整个集合。
  • \(h(S) = \sum _ { x \in S } h' ( x )\)
    • \(h'\):对每个 \(x\) 赋一个随机值(相同的 \(x\) 赋的值相同)。
  • 一个性质——判断集合中每个数的出现次数是否都是 \(k\) 的倍数(出现次数为 \(0\) 也可以):
    • 求和有对取模很友好的性质:如果一个数值的出现次数 \(\bmod k = 0\),那么它的哈希值加起来 \(\bmod k\) 也为 \(0\)。如果每个数值的哈希值之和 \(\bmod k = 0\),那么整个集合的哈希值(每个数的哈希值加起来,即每个数值的哈希值之和加起来)就也 \(\bmod k = 0\)。因此原命题能推出 Sum Hashing 的值 \(\bmod k = 0\),那么后者就是前者的必要条件。
    • 看 Sum Hashing 的值 \(\bmod k\) 是否为 \(0\)
      • 如果不为 \(0\) 则说明集合中 每个数的出现次数都是 \(k\) 的倍数 一定不成立
      • 如果为 \(0\) 则说明 ~ 可能成立
      • [蒙特卡罗判定]。
    • 随机较多遍之后错误率就小到可以接受了。
    • 题、错误率分析见:CF1746F Kazaee

Xor Hashing

  • 二进制 Xor Hashing [较常见]。
  • \(k\) 进制 Xor Hashing。
    • 每一位分别相加,不进位,分别对 \(k\) 取模。
  • 哈希值 一般 不表示整个集合只表示每个元素出现次数 \(\bmod k\) 是否为 \(0\)
    • 如果集合中每个元素的出现次数都 \(\leq k\),Xor Hashing 表示的就是整个集合。
  • 本质:
    • 把很多遍 取模的 Sum Hashing(就是上面写的 Sum Hashing 的“一个性质”部分)压到一起跑。因为每一位是独立的,每一位都相当于一次取模的 Sum Hashing。
  • 错误率:
    • 二进制 Xor Hashing 的话,在 [[int 或 long long]] 范围内随机,[一般] 这样跑一遍的错误率就刚好小到可以接受了。
  • 相比 Sum Hashing 的优势:
    • (二进制 Xor Hashing)二进制压缩,去掉了跑很多遍带的大概一只 \(\log\)
    • 异或性质优美,有时有妙用。(下面是二进制的,[更高的] 进制我不知道)
      • 重复直接消掉:
        • 树上简单路径的异或和:直接算到根的异或和,异或起来即可。
      • [异或线性基]。(我还不清楚正确率)(咕咕咕)

序列哈希

  • 把下标加入计算中,从而 [表现] [有序性]。
  • 字符串哈希。(多项式哈希。)
  • 作用:判定相等。
  • 可以预处理 Base 的幂来 \(O(1)\) 取出一段的哈希值。
  • 双哈希。

树哈希

还不会呜呜呜。

数据结构维护哈希值

  • 哈希表。
  • 其他数据结构。

咕咕咕。

以后来放题。

参考


2024.11.13

posted @ 2024-11-22 16:02  huangkxQwQ  阅读(7)  评论(0编辑  收藏  举报