1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//! # Succinct Data Structures
//!
//! *Near-optimal space with efficient queries.*
//!
//! ## Intuition First
//!
//! Imagine a library where every book is stored in a tightly packed vacuum-sealed bag.
//! It takes up the absolute minimum space (the information-theoretic limit).
//! Usually, to find a specific page, you'd have to unseal the whole bag (decompress).
//!
//! Succinct data structures allow you to "reach through" the vacuum seal and read
//! specific pages, count words, or find the k-th occurrence of a character—all
//! without unsealing the bag.
//!
//! ## The Problem
//!
//! Traditional data structures face a trade-off:
//! - **Pointers**: Fast queries ($O(1)$) but massive overhead ($O(n \log n)$ bits).
//! - **Compression**: Minimal space ($\log |C_n|$ bits) but no random access or queries ($O(n)$ to decompress).
//!
//! ## Historical Context
//!
//! ```text
//! 1971 Fano Fano's associative memory: early partitioning of bits
//! 1974 Elias Elias's static file storage: monotone sequences
//! 1989 Jacobson Defined the succinct paradigm in his PhD thesis (rank/select)
//! 1996 Munro-Raman Constant-time rank and select in o(n) extra space
//! 2003 Grossi Wavelet trees for rank/select over arbitrary alphabets
//! 2007 Ferragina FM-index: compressed full-text search (the "BWT" era)
//! 2022 Kurpicz Modern engineering of rank9/select9 structures
//! ```
//!
//! Guy Jacobson's key insight was that for many objects (like trees or bit vectors),
//! we can build auxiliary structures that are much smaller than the data itself ($o(n)$ bits)
//! but provide enough information to answer queries in constant time.
//!
//! ## Mathematical Formulation
//!
//! A data structure for a class of objects $C_n$ is:
//! - **Implicit**: Uses $\log |C_n| + O(1)$ bits.
//! - **Succinct**: Uses $\log |C_n| + o(\log |C_n|)$ bits.
//! - **Compact**: Uses $O(\log |C_n|)$ bits.
//!
//! The fundamental operations are:
//! - `rank(i)`: The number of set bits (1s) in the range $[0, i]$.
//! - `select(k)`: The position of the $k$-th set bit.
//!
//! ## Complexity Analysis
//!
//! - **Time**: $O(1)$ for rank/select in most modern implementations.
//! - **Space**: OPT + $o(n)$ bits (typically 5-20% overhead for auxiliary structures).
//!
//! ## What Could Go Wrong
//!
//! 1. **Static vs Dynamic**: Most succinct structures are static. Inserting into a
//! succinct bit vector usually requires rebuilding the auxiliary structures.
//! 2. **Cache Locality**: Constant time $O(1)$ doesn't mean "fast" if it requires
//! multiple random memory lookups for large bitsets.
//!
//! ## Implementation Notes
//!
//! This crate provides:
//! - **`BitVector`**: Core storage with rank/select support.
//! - **`WaveletTree`**: Rank/select over larger alphabets.
//! - **`EliasFano`**: Monotone sequences with random access.
//! - **`PartitionedEliasFano`**: Block-local encoding for clustered monotone sequences.
//!
//! ## References
//!
//! - Jacobson, G. (1989). "Succinct Static Data Structures."
//! - Munro, J. I., & Raman, V. (1996). "Selection and counting on the fly."
//! - Grossi, R., et al. (2003). "High-order entropy-compressed text indexes."
extern crate alloc;
extern crate std;
pub use BitVector;
pub use EliasFano;
pub use Error;
pub use PartitionedEliasFano;
pub use WaveletTree;