Skip to content

Commit

Permalink
Make cartesian tree building more efficient by traversing array left-…
Browse files Browse the repository at this point in the history
…to-right
  • Loading branch information
ot committed Oct 16, 2012
1 parent 477ffaa commit f847173
Showing 1 changed file with 30 additions and 31 deletions.
61 changes: 30 additions & 31 deletions cartesian_tree.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include <stack>
#include <vector>

#include <boost/range.hpp>

Expand All @@ -20,60 +20,59 @@ namespace succinct {
typedef typename
boost::range_value<Range>::type value_type;
typedef typename
boost::range_reverse_iterator<const Range>::type riter_type;
boost::range_iterator<const Range>::type iter_type;

// XXX int
typedef std::pair<value_type, int> value_pos_type;
std::stack<value_pos_type> s;
typedef std::pair<value_type, size_t> value_pos_type;
std::vector<value_pos_type> s;
size_t idx = 0;

std::vector<bool> bp;

int p = 0;
uint64_t n = 2 * boost::size(v) + 2;
bit_vector_builder bp(n);
uint64_t i = n - 1;

for (riter_type it = boost::rbegin(v); it != boost::rend(v); ++it) {
value_pos_type cur(*it, p--);
bp.push_back(0);
for (iter_type it = boost::begin(v); it != boost::end(v); ++it) {
value_pos_type cur(*it, idx++);
i--; // prepend 0

while (!s.empty() && s.top() > cur) {
s.pop();
bp.push_back(1);
while (!s.empty() && s.back() > cur) {
s.pop_back();
bp.set(i--, 1); // prepend 1
}

s.push(cur);
s.push_back(cur);
}

bp.push_back(0); // fake root
i--; // fake root

while (!s.empty()) {
s.pop();
bp.push_back(1);
s.pop_back();
bp.set(i--, 1);
}

bp.push_back(1); // fake root
bp.set(i--, 1);

std::reverse(bp.begin(), bp.end());

// XXX reverse select support?
bp_vector(bp, false, true).swap(m_bp);
bp_vector(&bp, false, true).swap(m_bp);
}

uint64_t rmq(uint64_t a, uint64_t b) const
{
assert(a <= b);
assert(a <= b);
if (a == b) return a;
uint64_t x = m_bp.select0(a + 1);
uint64_t y = m_bp.select0(b + 1);

uint64_t n = size();
uint64_t y = m_bp.select0(n - a);
uint64_t x = m_bp.select0(n - b);
uint64_t w = m_bp.excess_rmq(x, y);

uint64_t ret;

ret = m_bp.rank0(w);
ret = n - m_bp.rank0(w);
assert(m_bp[w - 1] == 0);

if (m_bp.rank0(m_bp.find_open(w - 1)) == a + 1) {
ret = a;
if (n - m_bp.rank0(m_bp.find_open(w - 1)) == b) {
ret = b;
} else {
ret = m_bp.rank0(w) - 1;
ret = n - m_bp.rank0(w);
}

assert(ret >= a);
Expand All @@ -86,7 +85,7 @@ namespace succinct {
return m_bp;
}

size_t size() const
uint64_t size() const
{
return m_bp.size() / 2 - 1;
}
Expand Down

0 comments on commit f847173

Please sign in to comment.