F - Rearrange Query 解説 by noshi91

ハッシュ関数の衝突確率について

公式解説にあるようなシンプルなハッシュ関数は、Schwartz-Zippel lemma を用いずとも衝突確率を抑えることができます。

多重集合 \(S, T\)\(S \neq T\) を満たす場合、\(S\) に含まれる個数と \(T\) に含まれる個数が異なるような要素 \(e\) が存在します。 \(e\) 以外の要素に割り当てられたハッシュ値を固定すると、\(H(S) - H(T)\)\(e\) に割り当てられたハッシュ値 \(x\) の関数として \(h + cx\) と表されます。 ここで \(h\) は何らかの定数で、\(c\)\(e\)\(S\) に含まれる個数と \(T\) に含まれる個数の差です。 \(N < P\) より \(c \neq 0 \pmod P\) ですから \(h + cx = 0 \pmod P \Leftrightarrow x = -h / c \pmod P\) と変形されて、\(x\)\(0 , 1 , \dots , P-1\) から一様ランダムに選ぶので衝突確率は \(1 / P\) です。

法を巨大な素数ではなく \(2^{64}\) にした場合も十分に安全です。 先ほどと同様に議論すると、\(c\) が偶数の場合に \({} \bmod 2^{64}\) 上で逆元を持たないため、\(h + cx = 0 \pmod {2^{64}}\)\(x = -h/c \pmod {2^{64}}\) に変形できないことが問題となります。 そこで、\(c\)\(2\) で割り切れる回数を \(k\) とします。 \(h\)\(2\)\(k\) 回以上割り切れない場合、\(h + cx = 0\) となる \(x\) は存在しないため衝突の恐れはありません。 \(k\) 回以上割り切れる場合、\(x = -h/c \pmod {2^{64-k}}\) と変形されます。 この式を満たす \(x\) を引く確率は \(1/2^{64-k}\) ですが、\(k \leq \log_2 N\) であるため \(2^{64-k}\) は十分に大きいです。 同様の議論により、\(2^{32}\) を法にした場合に \(1/30000\) 程度の確率で衝突してしまうことも分かります。

投稿日時:
最終更新: