// Computes N_1+( * ab * ) uint64_t N1PlusFrontBack(const node_type& node, const node_type& node_rev, pattern_iterator pattern_begin, pattern_iterator pattern_end) const { auto timer = lm_bench::bench(timer_type::N1PlusFrontBack); // ASSUMPTION: lb, rb already identify the suffix array range corresponding to 'pattern' in // the forward tree // ASSUMPTION: pattern_begin, pattern_end cover just the pattern we're interested in (i.e., // we want N1+ dot pattern dot) uint64_t pattern_size = std::distance(pattern_begin, pattern_end); uint64_t back_N1plus_front = 0; // this is when the pattern matches a full edge in the CST if (!m_cst.is_leaf(node) && pattern_size == m_cst.depth(node)) { if (*pattern_begin == PAT_START_SYM) { return m_cst.degree(node); } auto w = m_cst.select_child(node, 1); auto root_id = m_cst.id(m_cst.root()); std::vector<uint64_t> new_pattern(pattern_begin, pattern_end); new_pattern.push_back(EOS_SYM); while (m_cst.id(w) != root_id) { auto lb_rev_stored = m_cst_rev.lb(node_rev); auto rb_rev_stored = m_cst_rev.rb(node_rev); uint64_t symbol = m_cst.edge(w, pattern_size + 1); assert(symbol != EOS_SYM); new_pattern.back() = symbol; // find the symbol to the right // (which is first in the reverse order) backward_search_wrapper(m_cst_rev.csa, lb_rev_stored, rb_rev_stored, symbol, lb_rev_stored, rb_rev_stored); back_N1plus_front += N1PlusBack(m_cst_rev.node(lb_rev_stored, rb_rev_stored), new_pattern.begin(), new_pattern.end()); w = m_cst.sibling(w); } return back_N1plus_front; } else { // special case, only one way of extending this pattern to the right if (*pattern_begin == PAT_START_SYM && *(pattern_end - 1) == PAT_END_SYM) { /* pattern must be 13xyz41 -> #P(*3xyz4*) == 0 */ return 0; } else if (*pattern_begin == PAT_START_SYM) { /* pattern must be 13xyzA -> #P(*3xyz*) == 1 */ return 1; } else { /* pattern must be *xyzA -> #P(*xyz*) == N1PlusBack */ return N1PlusBack(node_rev, pattern_begin, pattern_end); } } }
iterator_type begin() const { return iterator_type(m_cst, m_cst->select_child(m_parent, 1)); }
node_type operator[](size_type i) const { return m_cst->select_child(m_parent, i + 1); } // enumeration starts with 1 not 0