# A subset lookup algorithm

Suppose I have a list $\cal X$ of subsets of $\{1, ..., n\}$. I can do preprocessing on this list if necessary. After this preprocessing, I am presented with another set $A \subseteq \{1, ..., n \}$. I want to identify any sets $B \in \mathcal X$ with $B \subseteq A$.

The obvious algorithm (without any preprocessing) takes time $O(n |\cal X|)$ -- you simply test $A$ against each $B \in \mathcal X$ separately. Is there anything better than this?

If it helps, you can assume that, for any $A$, the total number of matches $B \in \mathcal X$ is bounded by something like $O(1)$.

This is not an answer. It is a simple but long observation. I hope it will be useful.

The decision version of your problem is: Does $\cal X$ contain a subset of $A$?

This problem is related to the problem of evaluating monotone boolean functions of $n$ variables. A subset of $\{1,\ldots,n\}$ is equivalent to an $n$-bitstring, so the family $\cal X$ is equivalent to a boolean function $f$ of $n$ variables. Given a function $f$, one can define the least monotone function that is not bigger than $f$, namely $g(y)=(\exists x\subseteq y,\,f(x))$. The original problem is then reduced to evaluating $g(A)$. Conversely, the problem of evaluating a monotone boolean function can be reduced to the original problem, either naively by taking $f=g$ or by choosing an $f$ that makes $\cal X$ smaller.

In practice BDDs tend to work well. So one possible approach is to build the BDD for $f$, derive from it the BDD for $g$, and then evaluate $g$. The average size of the BDD for $g$ must be $\Omega\left(\binom{n}{n/2}\right)$, because there are many monotone boolean functions. Hence, in theory this is a bad solution.

But (1) a better analysis might be possible and (2) there might be tweaks to this approach that make it better. For example, I didn't use in any way the correlation between the size of $\cal X$ and the size of $g$'s BDD. (There must be a correlation, but I don't know if it is simple or usable here.)

For completeness, a simple algorithm for computing the BDD for $g$ from the BDD for $f$ is the following. $$m(x?f_1:f_0)=x?(m(f_0)\lor m(f_1)):m(f_0)$$ Here $\lor$ is the standard or-operation on BDDs.

• Isn't this more or less equivalent to precalculating the answer for each subset of $\{1,2,...,n\}$, caching all the results in a binary tree of size $2^n$, and then looking up the right result (in time $O(n)$) when you're given $A$? – mjqxxxx Jan 3 '12 at 20:48
• Using exponential space to store preprocessed data sounds like cheating to me, although it is not prohibited in the question. But I may be biased toward the Church of Worst-Case Complexity. – Tsuyoshi Ito Jan 4 '12 at 14:13
• mjqxxxx and Tsuyoshi: I agree with both of you. I rewrote the text so that, I hope, it is more clear that I agree. :) – Radu GRIGore Jan 5 '12 at 0:36

Perhaps you can use an "information retrieval" technique: in the preprocessing phase, build an inverted index (in your case a simple $n \times | {\cal X}|$ bidimensional array is enough) that maps an element $x_i \in \{1,...,n\}$ to the sets in $\cal X$ that contain it: $inv(x_i)= \{ X_j \in {\cal X} \; | \; x_i \in X_j \}$.

Set up an integer array $occ$ of length $|\cal X|$.

Then for each $y_i \in A$ retrieve $inv(y_i)$, and for each $X_j \in inv(y_i)$ do $occ[j] = occ[j]+1$

At the end the sets you need are those for which $|X_j|=occ[j]$.

You can arbitrarily speed up the process (at the cost of exponential space) by indexing two or more elements together.