Imagine a long sequence of characters drawn from an alphabet — say, the DNA string ACGTACGTACGT, or a million integers from 1 to 1000. You want to answer queries like:
- Rank: how many times does the letter
Gappear in the first 7 positions? - Select: where is the 3rd occurrence of
C? - k-th smallest: what is the 4th smallest value in positions 5 through 10?
You could sort for some queries and keep a separate inverted index for others. Or you could build a single wavelet tree — a structure invented by Grossi, Gupta and Vitter in 2003 — and answer all of them in time, where is the alphabet size, using space very close to the information-theoretic lower bound.
The key idea is binary recursion: split the alphabet in half, record for each position whether its symbol belongs to the lower or upper half (one bit per position), then recurse on the two sub-sequences. Each level of the tree is just a bit-vector supporting rank and select in after preprocessing — and levels is all you need to identify any symbol.
It sounds almost too simple. The remarkable part is how many apparently unrelated queries collapse into a handful of rank/select calls on those bit-vectors.
Comments
Loading comments...