Succinct dictionary
(Mylib/DataStructure/WaveletMatrix/succinct_dictionary.cpp)
Operations
Requirements
Notes
Problems
References
Required by
Verified with
Code
#pragma once
#include <cassert>
#include <optional>
#include <vector>
namespace haar_lib {
class succinct_dict {
int N_;
static const int chunk_size_ = 256;
static const int block_size_ = 64;
std::vector<uint64_t> data_;
std::vector<std::vector<uint8_t>> blocks_;
std::vector<uint32_t> chunks_;
int chunk_num_;
static const int block_num_ = chunk_size_ / block_size_;
public:
succinct_dict() : N_(0) {}
succinct_dict(const std::vector<bool> &b) : N_(b.size()) {
chunk_num_ = (N_ + chunk_size_ - 1) / chunk_size_;
data_.assign(chunk_num_ * block_num_ + 1, 0);
for (int i = 0; i < N_; ++i) {
if (b[i]) {
int block_index = i / block_size_;
int index = i % block_size_;
data_[block_index] |= (1LL << index);
}
}
chunks_.assign(chunk_num_ + 1, 0);
blocks_.assign(chunk_num_ + 1, std::vector<uint8_t>(block_num_, 0));
for (int i = 0; i < chunk_num_; ++i) {
for (int j = 0; j < block_num_ - 1; ++j) {
blocks_[i][j + 1] = blocks_[i][j] + __builtin_popcountll(data_[i * block_num_ + j]);
}
chunks_[i + 1] = chunks_[i] + blocks_[i][block_num_ - 1] + __builtin_popcountll(data_[(i + 1) * block_num_ - 1]);
}
}
int size() const { return N_; }
/**
* @return [0, index)のbの個数
*/
int rank(int index, int b) const {
if (b == 0) {
return index - rank(index, 1);
} else {
if (index > N_) index = N_;
const int chunk_pos = index / chunk_size_;
const int block_pos = (index % chunk_size_) / block_size_;
const uint64_t mask =
data_[chunk_pos * block_num_ + block_pos] & ((1LL << (index % block_size_)) - 1);
const int ret = chunks_[chunk_pos] +
blocks_[chunk_pos][block_pos] +
__builtin_popcountll(mask);
return ret;
}
}
/**
* @return [l, r)のbの個数
*/
int count(int l, int r, int b) const {
return rank(r, b) - rank(l, b);
}
/**
* @return b[index]
*/
int access(int index) const {
return (data_[index / block_size_] >> (index % block_size_)) & 1;
}
/**
* @note n in [1, N]
* @return 先頭からn番目のbの位置
*/
std::optional<int> select(int n, int b) const {
assert(n >= 1);
if (rank(N_, b) < n) return {};
int lb = -1, ub = N_;
while (std::abs(lb - ub) > 1) {
int mid = (lb + ub) / 2;
if (rank(mid, b) >= n) {
ub = mid;
} else {
lb = mid;
}
}
return {lb};
}
};
} // namespace haar_lib
#line 2 "Mylib/DataStructure/WaveletMatrix/succinct_dictionary.cpp"
#include <cassert>
#include <optional>
#include <vector>
namespace haar_lib {
class succinct_dict {
int N_;
static const int chunk_size_ = 256;
static const int block_size_ = 64;
std::vector<uint64_t> data_;
std::vector<std::vector<uint8_t>> blocks_;
std::vector<uint32_t> chunks_;
int chunk_num_;
static const int block_num_ = chunk_size_ / block_size_;
public:
succinct_dict() : N_(0) {}
succinct_dict(const std::vector<bool> &b) : N_(b.size()) {
chunk_num_ = (N_ + chunk_size_ - 1) / chunk_size_;
data_.assign(chunk_num_ * block_num_ + 1, 0);
for (int i = 0; i < N_; ++i) {
if (b[i]) {
int block_index = i / block_size_;
int index = i % block_size_;
data_[block_index] |= (1LL << index);
}
}
chunks_.assign(chunk_num_ + 1, 0);
blocks_.assign(chunk_num_ + 1, std::vector<uint8_t>(block_num_, 0));
for (int i = 0; i < chunk_num_; ++i) {
for (int j = 0; j < block_num_ - 1; ++j) {
blocks_[i][j + 1] = blocks_[i][j] + __builtin_popcountll(data_[i * block_num_ + j]);
}
chunks_[i + 1] = chunks_[i] + blocks_[i][block_num_ - 1] + __builtin_popcountll(data_[(i + 1) * block_num_ - 1]);
}
}
int size() const { return N_; }
/**
* @return [0, index)のbの個数
*/
int rank(int index, int b) const {
if (b == 0) {
return index - rank(index, 1);
} else {
if (index > N_) index = N_;
const int chunk_pos = index / chunk_size_;
const int block_pos = (index % chunk_size_) / block_size_;
const uint64_t mask =
data_[chunk_pos * block_num_ + block_pos] & ((1LL << (index % block_size_)) - 1);
const int ret = chunks_[chunk_pos] +
blocks_[chunk_pos][block_pos] +
__builtin_popcountll(mask);
return ret;
}
}
/**
* @return [l, r)のbの個数
*/
int count(int l, int r, int b) const {
return rank(r, b) - rank(l, b);
}
/**
* @return b[index]
*/
int access(int index) const {
return (data_[index / block_size_] >> (index % block_size_)) & 1;
}
/**
* @note n in [1, N]
* @return 先頭からn番目のbの位置
*/
std::optional<int> select(int n, int b) const {
assert(n >= 1);
if (rank(N_, b) < n) return {};
int lb = -1, ub = N_;
while (std::abs(lb - ub) > 1) {
int mid = (lb + ub) / 2;
if (rank(mid, b) >= n) {
ub = mid;
} else {
lb = mid;
}
}
return {lb};
}
};
} // namespace haar_lib
Back to top page