Algorithm Search⌘K

Proofs: FKS perfect hashing

These are the human proofs of FKS perfect hashing, at full length.

FKS perfect hashing builds in O(n) expected time and uses O(n) space full

This proof shows: time.expected, space.extra.

We use one fact about the family ha,b,m(x)=((ax+b) mod p) mod mh_{a,b,m}(x) = ((ax + b) \bmod p) \bmod m, with aa uniform in {1,…,p−1}\{1, \ldots, p - 1\} and bb uniform in {0,…,p−1}\{0, \ldots, p - 1\}:

(U) For each m≥1m \ge 1 and each two distinct keys x≠yx \ne y of {0,…,p−1}\{0, \ldots, p - 1\}, Pr⁡[ha,b,m(x)=ha,b,m(y)]≤1/m\Pr[h_{a,b,m}(x) = h_{a,b,m}(y)] \le 1/m.

This is the universality of the Carter and Wegman family, proved in CLRS, Section 11.3 (fourth edition) and Section 11.3.3 (third edition). The model is the word RAM with p<2wp < 2^w, so each hash value costs O(1)O(1).

Lemma 1 (collisions). Let X⊆{0,…,p−1}X \subseteq \{0, \ldots, p - 1\} have kk keys, let h=ha,b,mh = h_{a,b,m} be random, and let CC be the number of unordered pairs {x,y}⊆X\{x, y\} \subseteq X with x≠yx \ne y and h(x)=h(y)h(x) = h(y). Then E[C]≤(k2)/mE[C] \le \binom{k}{2} / m.

Proof. CC is the sum, over the (k2)\binom{k}{2} pairs, of the indicator of the event h(x)=h(y)h(x) = h(y). By (U), each indicator has expectation at most 1/m1/m. By linearity of expectation, E[C]≤(k2)/mE[C] \le \binom{k}{2}/m. □\square

Lemma 2 (sum of squares). If the buckets of hh on XX have sizes k0,…,km−1k_0, \ldots, k_{m-1}, then ∑jkj2=k+2C\sum_j k_j^2 = k + 2C.

Proof. For each integer t≥0t \ge 0, t2=t+2(t2)t^2 = t + 2 \binom{t}{2}. Bucket jj contains (kj2)\binom{k_j}{2} colliding pairs, and each colliding pair lies in exactly one bucket, so C=∑j(kj2)C = \sum_j \binom{k_j}{2}. Summing kj2=kj+2(kj2)k_j^2 = k_j + 2\binom{k_j}{2} over jj and using ∑jkj=k\sum_j k_j = k gives the claim. □\square

Claim 1 (first level). One trial of lines L3 to L5 succeeds with probability more than 1/21/2.

Proof. If n=0n = 0, the sum is 0≤00 \le 0 and the trial succeeds. Let n≥1n \ge 1, so m=nm = n. By Lemmas 1 and 2, E[∑jnj2]=n+2E[C]≤n+2(n2)/n=n+(n−1)=2n−1E[\sum_j n_j^2] = n + 2E[C] \le n + 2 \binom{n}{2}/n = n + (n - 1) = 2n - 1. The sum is a non-negative random variable, so by Markov's inequality Pr⁡[∑jnj2>4n]≤Pr⁡[∑jnj2≥4n]≤(2n−1)/(4n)<1/2\Pr[\sum_j n_j^2 > 4n] \le \Pr[\sum_j n_j^2 \ge 4n] \le (2n - 1)/(4n) < 1/2. □\square

Claim 2 (second level). For a bucket with nj≥1n_j \ge 1 keys and mj=nj2m_j = n_j^2, one trial of lines L9 and L10 succeeds with probability more than 1/21/2.

Proof. If nj=1n_j = 1, there is no pair and each trial succeeds. Let nj≥2n_j \ge 2, and let CjC_j be the number of colliding pairs of SjS_j under hjh_j. The choice of hjh_j is independent of the choice of hh, and SjS_j is fixed once hh is fixed, so Lemma 1 applies to X=SjX = S_j: E[Cj]≤(nj2)/nj2=(nj−1)/(2nj)<1/2E[C_j] \le \binom{n_j}{2}/n_j^2 = (n_j - 1)/(2 n_j) < 1/2. CjC_j is a non-negative integer, so by Markov's inequality Pr⁡[Cj≥1]≤E[Cj]<1/2\Pr[C_j \ge 1] \le E[C_j] < 1/2. The trial succeeds exactly when Cj=0C_j = 0. □\square

Theorem (time and space). FKS-BUILD runs in O(n)O(n) expected time. The structure has at most 4n4n second-level slots and O(n)O(n) words in total, in every run.

Proof. Space. The loop of lines L2 to L5 ends only when ∑jnj2≤4n\sum_j n_j^2 \le 4n, and ∑jmj=∑jnj2\sum_j m_j = \sum_j n_j^2. The first level stores m=max⁡(n,1)m = \max(n, 1) triples (mj,aj,bj)(m_j, a_j, b_j) and the pair (a,b)(a, b). So the total is at most 4n+3max⁡(n,1)+2=O(n)4n + 3\max(n, 1) + 2 = O(n) words.

Time of the first level. A trial costs O(n+m)=O(n+1)O(n + m) = O(n + 1): one hash value for each key, and mm lists. By Claim 1 and the geometric distribution of the number of trials, the expected number of trials is less than 2. So the first level takes O(n+1)O(n + 1) expected time.

Time of the second level. Condition on the accepted hh, so that the sizes njn_j are fixed with ∑jnj2≤4n\sum_j n_j^2 \le 4n. Bucket jj costs O(1+mj)O(1 + m_j) for line L7, and O(nj)O(n_j) for each trial of lines L9 and L10, since a trial writes at most njn_j slots and clears the ones it wrote. By Claim 2, the expected number of trials is less than 2. Line L11 costs O(nj)O(n_j). So the expected cost of bucket jj is O(1+mj+nj)O(1 + m_j + n_j), and, by linearity of expectation, the second level costs O(m+∑jmj+n)=O(n+1)O(m + \sum_j m_j + n) = O(n + 1) in expectation, for each accepted hh. Taking the expectation over hh keeps the bound.

Adding the two levels gives O(n+1)O(n + 1) expected time, which is O(n)O(n) for n≥1n \ge 1. ■\blacksquare

Search. FKS-SEARCH evaluates two hash functions and reads two arrays, so it takes O(1)O(1) time in every case.

FKS-SEARCH answers membership correctly, and FKS-BUILD ends with probability 1 full

This proof shows: correctness, termination.

Let S⊆{0,…,p−1}S \subseteq \{0, \ldots, p - 1\} be a set of nn distinct keys, with pp prime. We write nj=∣Sj∣n_j = |S_j| for the size of bucket jj after the loop of lines L2 to L5.

Lemma 1 (the stored table). When FKS-BUILD returns, for each jj with nj>0n_j > 0, the array TjT_j holds exactly the keys of SjS_j, and each x∈Sjx \in S_j is in the slot Tj[hj(x)]T_j[h_j(x)]. For each jj with nj=0n_j = 0, mj=0m_j = 0.

Proof. Fix jj. Line L7 sets mj=nj2m_j = n_j^2, so mj=0m_j = 0 exactly when nj=0n_j = 0. If nj>0n_j > 0, the loop of lines L9 and L10 ends only with a function hjh_j that gives distinct slots to distinct keys of SjS_j. Line L11 writes each x∈Sjx \in S_j to Tj[hj(x)]T_j[h_j(x)]. Two keys of SjS_j never write the same slot, so no write is lost, and after line L11 the slots of TjT_j that are not NIL hold exactly the njn_j keys of SjS_j. No later step changes TjT_j. □\square

Theorem 1 (search). After FKS-BUILD(S)(S), FKS-SEARCH(x)(x) returns true if x∈Sx \in S and false if x∉Sx \notin S, for each x∈{0,…,p−1}x \in \{0, \ldots, p - 1\}.

Proof. Let j=h(x)j = h(x), the value of line L12.

Case x∈Sx \in S. By line L4, x∈Sjx \in S_j, so nj≥1n_j \ge 1 and mj≥1m_j \ge 1, and line L13 does not return. By Lemma 1, Tj[hj(x)]=xT_j[h_j(x)] = x, so line L14 returns true.

Case x∉Sx \notin S. If mj=0m_j = 0, line L13 returns false. Else, by Lemma 1, the slot Tj[hj(x)]T_j[h_j(x)] holds NIL or a key of Sj⊆SS_j \subseteq S. Neither is equal to xx, since x∉Sx \notin S. So line L14 returns false. □\square

Theorem 2 (termination). FKS-BUILD ends with probability 1, and the expected number of trials of each loop is less than 2.

Proof. The complexity proof shows that one trial of lines L3 to L5 meets the test of line L5 with probability q>1/2q > 1/2, and that, for each jj with nj>0n_j > 0, one trial of lines L9 and L10 meets the test of line L10 with probability qj>1/2q_j > 1/2. The trials of one loop use independent random choices, so the probability that the first tt trials all fail is (1−q)t<2−t(1 - q)^t < 2^{-t}, which tends to 0. So each loop ends with probability 1, and the number of its trials has a geometric distribution with mean 1/q<21/q < 2 (or 1/qj<21/q_j < 2). There are m+1m + 1 loops, a finite number, so the build ends with probability 1. ■\blacksquare

Back to FKS perfect hashing