cai_lw's competitive programming library
 
Loading...
Searching...
No Matches
bit_dict.hpp
1#pragma once
2
3#include <climits>
4#include <cstdint>
5#include <memory>
6#include <vector>
7
8#include "cplib/port/bit.hpp"
9#include "cplib/utils/bit.hpp"
10
11namespace cplib {
12
13namespace impl {
14
15class alignas(64) BitDictBlock {
16 public:
17 using size_type = std::size_t;
18 using word_type = std::uint64_t;
19 static constexpr size_type words_per_block = 6;
20 static constexpr size_type word_size = std::numeric_limits<word_type>::digits;
21 static constexpr size_type block_size = word_size * words_per_block;
22
23 BitDictBlock() : data_({0}) {}
24
25 size_type build(size_type block_rank) {
26 block_rank_ = block_rank;
27 wrap_word_ = words_per_block;
28 size_type acc_rank = 0;
29 for (int i = 0; i < words_per_block; i++) {
30 if (acc_rank >= 256 && wrap_word_ == words_per_block) {
31 wrap_word_ = i;
32 }
33 word_rank_[i] = acc_rank;
34 acc_rank += port::popcount(data_[i]);
35 }
36 return block_rank_ + acc_rank;
37 }
38
39 bool get(size_type idx) const { return (data_[idx / word_size] >> (idx % word_size)) & 1; }
40
41 void set(size_type idx) { data_[idx / word_size] |= word_type(1) << (idx % word_size); }
42
43 size_type rank(size_type idx) const {
44 size_type word_idx = idx / word_size;
45 return block_rank_ + get_word_rank_(word_idx) + impl::popcount_low(data_[word_idx], idx % word_size);
46 }
47
48 private:
49 size_type get_word_rank_(size_type idx) const { return word_rank_[idx] + (idx >= wrap_word_) * 256; }
50
51 std::array<word_type, words_per_block> data_;
52 size_type block_rank_;
53 std::array<std::uint8_t, words_per_block> word_rank_;
54 std::uint8_t wrap_word_;
55};
56
57static_assert(sizeof(BitDictBlock) == 64);
58
59} // namespace impl
60
73class BitDict {
74 public:
75 using size_type = impl::BitDictBlock::size_type;
76
78 BitDict() : size_(0), zeros_(0) {}
79
85 BitDict(size_type num_bits) : size_(num_bits), blocks_(num_bits / block_size + 1) {}
86
88 size_type size() const { return size_; }
89
91 size_type zeros() const { return zeros_; }
92
94 size_type ones() const { return size_ - zeros_; }
95
97 bool get(size_type idx) const { return blocks_[idx / block_size].get(idx % block_size); }
98
104 void set(size_type idx) { blocks_[idx / block_size].set(idx % block_size); }
105
111 template <typename BitGenerator>
112 void fill_with_bit_generator(BitGenerator& gen) {
113 for (size_type i = 0; i < size_; i++) {
114 if (gen()) {
115 set(i);
116 }
117 }
118 }
119
121 void build() {
122 size_type acc_rank = 0;
123 for (auto& block : blocks_) {
124 acc_rank = block.build(acc_rank);
125 }
126 zeros_ = size_ - acc_rank;
127 }
128
134 size_type rank1(size_type idx) const { return blocks_[idx / block_size].rank(idx % block_size); }
135
138 size_type rank0(size_type idx) const { return idx - rank1(idx); }
139
151 size_type rank_to_child(size_type idx, bool bit) const { return bit ? zeros() + rank1(idx) : rank0(idx); }
152
153 private:
154 static constexpr size_type block_size = impl::BitDictBlock::block_size;
155 std::vector<impl::BitDictBlock> blocks_;
156 size_type size_, zeros_;
157};
158
159} // namespace cplib
Static bit sequence with rank query in .
Definition: bit_dict.hpp:73
size_type zeros() const
Returns the number of zero bits.
Definition: bit_dict.hpp:91
size_type rank_to_child(size_type idx, bool bit) const
Move one level downwards in a wavelet tree.
Definition: bit_dict.hpp:151
void fill_with_bit_generator(BitGenerator &gen)
Overwrite all bits with a bit generator.
Definition: bit_dict.hpp:112
size_type ones() const
Returns the number of one bits.
Definition: bit_dict.hpp:94
size_type size() const
Returns the number of bits.
Definition: bit_dict.hpp:88
BitDict()
Creates an empty BitDict.
Definition: bit_dict.hpp:78
BitDict(size_type num_bits)
Creates a BitDict with num_bits bits, all initialized to 0.
Definition: bit_dict.hpp:85
size_type rank1(size_type idx) const
Returns the number of 1 bits in the range [0, idx).
Definition: bit_dict.hpp:134
bool get(size_type idx) const
Read-only access to a bit. Requires 0 <= idx < size()
Definition: bit_dict.hpp:97
void build()
Set up auxiliary data to prepare for rank queries.
Definition: bit_dict.hpp:121
size_type rank0(size_type idx) const
Returns the number of 0 bits in the range [0, idx).
Definition: bit_dict.hpp:138
void set(size_type idx)
Set a bit to 1. Requires 0 <= idx < size().
Definition: bit_dict.hpp:104