In the approximate membership problem, we have subset S⊂US \subset U, that supports two operations:

  1. update(xx): S←S∪{x}S \leftarrow S \cup \{x\}
  2. query(xx): return True if x∈Sx\in S else False.

where UU is the domain that elements xx belongs to. If U=232U = 2^{32}, then each representation of xx takes 3232 bits. If U=264U = 2^{64}, then each xx needs 6464 bits. If UU is the website address, the length of its elements might is unlimited. Suppose that the average length is about 1515 chars, and each char takes 88 bits, then the representation could occupy most 120120 bits.

We can solve the membership problem exactly by dictionaries, such as balanced-binary search tree and hash set. This requires space O(nlog⁡U)O(n \log U) bits. If we allows false positive, we can break this bound.

The idea is to have a bit array AA with length O(kn)O(kn) bits and a pairwise hash family HH that maps the elements in UU uniformly at random to each bit in the array. After picking a hash function uniformly at random from HH, the operation on SS is performed as follows:

  1. update(xx): A[h(x)]←1A[h(x)] \leftarrow 1
  2. query(xx): return True if A[h(x)]=1A[h(x)] = 1 else False.

We can only make a mistake if an element y∉Sy \notin S and A[h(y)]=1A[h(y)] = 1. However, the probability of such event is bounded by

Pr⁡[∃x∈S,s.t.,h(x)=h(y)]≤∑x∈SPr⁡[h(x)=h(y)]=nm=1k \Pr[\exists x \in S, s.t., h(x) = h(y)] \le \sum_{x \in S} \Pr[h(x) = h(y)] = \frac{n}{m} = \frac{1}{k}

Remark: the accurate probability is given by

1−Pr⁡[∀x∈S,s.t.,h(x)≠h(y)]=1−(1−1m)n≤nm 1 - \Pr[\forall x \in S, s.t., h(x) \neq h(y)] = 1 - (1 - \frac{1}{m})^n \le \frac{n}{m}

To amplify the failure probability to a specified threshold δ\delta, we can set k=1δk = \frac{1}{\delta}. A more efficient way is by repetition the array ln⁡1δ/ln⁡k\ln \frac{1}{\delta} /\ln k times. Then the overall space usage is

nkln⁡1δln⁡k \frac{ n k \ln \frac{1}{\delta} }{ \ln k }

Note that f(k)=kln⁡k≥ef(k) = \frac{k}{\ln k} \ge e, since it holds that y=x−eln⁡xy = x - e\ln x (click to see the plot) for x>0x > 0:

y′=1−e/x=0⟶x=e. y' = 1 - e / x = 0 \longrightarrow x = e.

When k=ek = e the space usage is

neln⁡1δ ne \ln \frac{1}{\delta}

The compress ratio is given by

log⁡Ueln⁡1δ \frac{\log U}{e \ln \frac{1}{\delta} }

If we require the failure probability δ=1/100\delta = 1 / 100, then ln⁡1/δ≈4.6\ln 1 / \delta \approx 4.6, and eln⁡1/δ≈12.5≤13e \ln 1/\delta \approx 12.5 \le 13. That is, we need on 1313 bits for each element in SS, and the average number of operations for updating SS is 55, which is about 1/21/2 space when U=232U = 2^{32}, 1/51/5 space when U=264U = 2^{64}, and much less when UU is the set of possible web addresses.

Remark

There is another implementation that use a single bit array AA of size mm but kk hash functions h1,h2,...,hkh_1, h_2, ..., h_k. We initialization by setting

For x∈Sx \in S:
\qquad set A[hi(x)]=1A[h_i(x)] = 1 for all i∈[k]i \in [k].

As a result, at most knkn bits of AA are initialized to be 1.

Now, for an element x′∉Sx' \notin S, we accidentally report it as a member ∈S\in S if hi(x′)=1h_i(x') = 1 for all i∈[k]i \in [k]. But the probability that

Pr⁡[hi(x′)=1]≤knm \Pr[h_i(x') = 1] \le \frac{kn}{m}

and

Pr⁡[hi(x′)=1,∀i∈[k]]≤(knm)k \Pr[h_i(x') = 1, \forall i \in [k]] \le (\frac{kn}{m} )^k

If we use k=ln⁡1δk = \ln \frac{1}{\delta} hash functions and set the size m=neln⁡1δm = ne \ln \frac{1}{\delta}, we can also achieve failure probability δ\delta.

Question to ponder: what is SS is dynamic?