29class SdslRmMTree :
public RmMBase<SdslRmMTree> {
31 using BpSupport = sdsl::bp_support_sada<>;
34 SdslRmMTree() =
default;
36 SdslRmMTree(std::span<const std::uint64_t> words,
37 std::size_t bit_count,
40 const std::size_t valid_words = (bit_count + 63) / 64;
41 for (std::size_t i = 0; i < valid_words; ++i) {
42 std::uint64_t word = words[i];
43 if (i + 1 == valid_words && (bit_count & 63) != 0) {
44 word &= (std::uint64_t{1} << (bit_count & 63)) - 1;
46 ones_ += std::popcount(word);
48 zeros_ = size_ - ones_;
50 bits_ = sdsl::bit_vector(size_);
51 prefix_excess_.assign(size_ + 1, 0);
52 int current_excess = 0;
53 for (std::size_t i = 0; i < size_; ++i) {
54 const bool bit = (words[i >> 6] >> (i & 63)) & 1u;
56 current_excess +=
bit ? 1 : -1;
57 prefix_excess_[i + 1] = current_excess;
58 max_excess_ = std::max(max_excess_, current_excess);
60 build_excess_bounds();
61 tree_ = BpSupport(&bits_);
64 SdslRmMTree(
const SdslRmMTree& other)
68 max_excess_(other.max_excess_),
69 prefix_excess_(other.prefix_excess_),
70 prefix_min_excess_(other.prefix_min_excess_),
71 prefix_max_excess_(other.prefix_max_excess_),
72 suffix_min_excess_(other.suffix_min_excess_),
73 suffix_max_excess_(other.suffix_max_excess_),
78 SdslRmMTree& operator=(
const SdslRmMTree& other) {
84 zeros_ = other.zeros_;
85 max_excess_ = other.max_excess_;
86 prefix_excess_ = other.prefix_excess_;
87 prefix_min_excess_ = other.prefix_min_excess_;
88 prefix_max_excess_ = other.prefix_max_excess_;
89 suffix_min_excess_ = other.suffix_min_excess_;
90 suffix_max_excess_ = other.suffix_max_excess_;
96 SdslRmMTree(SdslRmMTree&& other) noexcept
100 max_excess_(other.max_excess_),
101 prefix_excess_(std::move(other.prefix_excess_)),
102 prefix_min_excess_(std::move(other.prefix_min_excess_)),
103 prefix_max_excess_(std::move(other.prefix_max_excess_)),
104 suffix_min_excess_(std::move(other.suffix_min_excess_)),
105 suffix_max_excess_(std::move(other.suffix_max_excess_)),
106 bits_(std::move(other.bits_)) {
110 SdslRmMTree& operator=(SdslRmMTree&& other)
noexcept {
111 if (
this == &other) {
116 zeros_ = other.zeros_;
117 max_excess_ = other.max_excess_;
118 prefix_excess_ = std::move(other.prefix_excess_);
119 prefix_min_excess_ = std::move(other.prefix_min_excess_);
120 prefix_max_excess_ = std::move(other.prefix_max_excess_);
121 suffix_min_excess_ = std::move(other.suffix_min_excess_);
122 suffix_max_excess_ = std::move(other.suffix_max_excess_);
123 bits_ = std::move(other.bits_);
128 std::size_t size_impl()
const {
return size_; }
130 std::size_t rank1_impl(std::size_t end_position)
const {
131 if (size_ == 0 || end_position == 0) {
134 return tree_.rank(std::min(end_position, size_) - 1);
137 std::size_t rank0_impl(std::size_t end_position)
const {
138 if (size_ == 0 || end_position == 0) {
141 if (end_position >= size_) {
144 return tree_.preceding_closing_parentheses(end_position);
147 std::size_t select1_impl(std::size_t rank)
const {
148 if (rank == 0 || rank > ones_) {
151 return tree_.select(rank);
154 std::size_t select0_impl(std::size_t)
const {
return npos; }
155 std::size_t rank10_impl(std::size_t)
const {
return 0; }
156 std::size_t select10_impl(std::size_t)
const {
return npos; }
158 int excess_impl(std::size_t end_position)
const {
159 if (size_ == 0 || end_position == 0) {
162 return tree_.excess(std::min(end_position, size_) - 1);
165 std::size_t fwdsearch_impl(std::size_t start_position,
int delta)
const {
166 if (start_position >= size_) {
169 const int target = prefix_excess_[start_position] + delta;
170 if (target > max_excess_) {
174 if (start_position == 0) {
175 const int first_excess = bits_[0] ? 1 : -1;
176 if (first_excess == delta) {
179 if (!suffix_contains(2, target)) {
182 const std::size_t position =
183 tree_.fwd_excess(0,
static_cast<typename BpSupport::difference_type
>(
184 delta - first_excess));
185 return position < size_ ? position : npos;
188 if (!suffix_contains(start_position + 1, target)) {
191 const std::size_t position = tree_.fwd_excess(
193 static_cast<typename BpSupport::difference_type
>(delta));
194 return position < size_ ? position : npos;
197 std::size_t bwdsearch_impl(std::size_t start_position,
int delta)
const {
198 if (start_position == 0 || start_position > size_) {
202 const std::size_t anchor = start_position - 1;
203 const int target = prefix_excess_[start_position] + delta;
204 if (target > max_excess_) {
207 if (prefix_excess_[anchor] == target) {
213 if (!prefix_contains(anchor - 1, target)) {
217 const std::size_t position = tree_.bwd_excess(
218 anchor,
static_cast<typename BpSupport::difference_type
>(delta));
219 if (position ==
static_cast<std::size_t
>(-1)) {
220 return target == 0 ? 0 : npos;
222 return position < size_ ? position + 1 : npos;
225 std::size_t range_min_query_pos_impl(std::size_t range_begin,
226 std::size_t range_end)
const {
230 return tree_.rmq(range_begin, range_end);
233 int range_min_query_val_impl(std::size_t range_begin,
234 std::size_t range_end)
const {
238 const auto min_position = tree_.rmq(range_begin, range_end);
239 if (min_position >= size_) {
242 const auto base_excess =
243 (range_begin == 0 ? 0 : tree_.excess(range_begin - 1));
244 return tree_.excess(min_position) - base_excess;
247 std::size_t range_max_query_pos_impl(std::size_t, std::size_t)
const {
250 int range_max_query_val_impl(std::size_t, std::size_t)
const {
return 0; }
251 std::size_t mincount_impl(std::size_t, std::size_t)
const {
return 0; }
252 std::size_t minselect_impl(std::size_t, std::size_t, std::size_t)
const {
256 std::size_t close_impl(std::size_t open_position)
const {
260 const std::size_t position = tree_.find_close(open_position);
261 return position < size_ ? position : npos;
264 std::size_t open_impl(std::size_t close_position)
const {
268 const std::size_t position = tree_.find_open(close_position);
269 return position < size_ ? position : npos;
272 std::size_t enclose_impl(std::size_t open_position)
const {
276 const std::size_t position = tree_.enclose(open_position);
277 return position < size_ ? position : npos;
280 int bit_impl(
const size_t& position)
const noexcept {
281 return (bits_[position >> 6] >> (position & 63)) & 1u;
285 void reset_support() { tree_ = BpSupport(&bits_); }
287 void build_excess_bounds() {
288 prefix_min_excess_.resize(size_ + 1);
289 prefix_max_excess_.resize(size_ + 1);
290 suffix_min_excess_.resize(size_ + 1);
291 suffix_max_excess_.resize(size_ + 1);
293 prefix_min_excess_[0] = prefix_excess_[0];
294 prefix_max_excess_[0] = prefix_excess_[0];
295 for (std::size_t i = 1; i <= size_; ++i) {
296 prefix_min_excess_[i] =
297 std::min(prefix_min_excess_[i - 1], prefix_excess_[i]);
298 prefix_max_excess_[i] =
299 std::max(prefix_max_excess_[i - 1], prefix_excess_[i]);
302 suffix_min_excess_[size_] = prefix_excess_[size_];
303 suffix_max_excess_[size_] = prefix_excess_[size_];
304 for (std::size_t i = size_; i > 0;) {
306 suffix_min_excess_[i] =
307 std::min(prefix_excess_[i], suffix_min_excess_[i + 1]);
308 suffix_max_excess_[i] =
309 std::max(prefix_excess_[i], suffix_max_excess_[i + 1]);
313 bool suffix_contains(std::size_t boundary_begin,
int target)
const {
314 return boundary_begin <= size_ &&
315 suffix_min_excess_[boundary_begin] <= target &&
316 target <= suffix_max_excess_[boundary_begin];
319 bool prefix_contains(std::size_t boundary_end,
int target)
const {
320 return prefix_min_excess_[boundary_end] <= target &&
321 target <= prefix_max_excess_[boundary_end];
326 std::size_t zeros_{};
328 std::vector<int> prefix_excess_;
329 std::vector<int> prefix_min_excess_;
330 std::vector<int> prefix_max_excess_;
331 std::vector<int> suffix_min_excess_;
332 std::vector<int> suffix_max_excess_;
333 sdsl::bit_vector bits_;