48#ifndef SUFFIX_STRUCTURES_H
49#define SUFFIX_STRUCTURES_H
63namespace suffix_structures_detail {
72 for (
size_t i = 0; i <= n; ++i)
100 const size_t n = text.
size();
109 for (
size_t i = 0; i < n; ++i)
112 rank[i] =
static_cast<unsigned char>(text[i]);
119 auto key2 = [&](
const size_t idx) ->
int
121 return (idx +
k < n) ? rank[idx +
k] : -1;
124 auto key1 = [&](
const size_t idx) ->
int
132 auto less_idx = [&](
const size_t a,
const size_t b)
134 if (rank[a] != rank[b])
135 return rank[a] < rank[b];
136 const int ra = (a +
k < n) ? rank[a +
k] : -1;
137 const int rb = (b +
k < n) ? rank[b +
k] : -1;
142 for (
size_t i = 1; i < n; ++i)
145 for (
size_t i = 0; i < n; ++i)
150 if (
max_rank ==
static_cast<int>(n - 1))
185 const size_t n = text.
size();
194 for (
size_t i = 0; i < n; ++i)
198 for (
size_t i = 0; i < n; ++i)
201 <<
"lcp_array_kasai(): suffix array contains invalid index";
203 <<
"lcp_array_kasai(): suffix array contains duplicate index";
208 for (
size_t i = 0; i < n; ++i)
210 const size_t r = rank[i];
217 const size_t j = sa[
r + 1];
218 while (i +
k < n
and j +
k < n
and text[i +
k] == text[j +
k])
245 static constexpr size_t npos = std::numeric_limits<size_t>::max();
267 std::array<bool, 256>
used;
269 for (
const unsigned char c : s)
272 for (
size_t i = 0; i < 256; ++i)
274 return static_cast<char>(i);
276 ah_domain_error() <<
"Naive_Suffix_Tree::choose_terminal(): all 256 byte values "
277 <<
"are present in the input; no terminal marker available";
282 size_t create_node(
const size_t start,
const size_t end,
const size_t parent,
const size_t suffix_index)
296 for (
size_t i = 0; i < children.
size(); ++i)
297 if (
const size_t child = children[i];
text_[
nodes_[child].start] == c)
318 while (pos <
text_.size())
324 nodes_[current].children.append(leaf);
399 void build(
const std::string_view text)
402 std::string
new_text(text.begin(), text.end());
411 for (
size_t i = 0; i <
text_.size(); ++i)
431 while (pos < pattern.size())
446 if (pos +
k == pattern.size())
482 while (pos < pattern.size())
497 if (pos +
k == pattern.size())
588 states_[
static_cast<size_t>(p)].terminal =
true;
589 p =
states_[
static_cast<size_t>(p)].link;
628 const auto c =
static_cast<unsigned char>(
ch);
630 const int cur =
static_cast<int>(
states_.size());
636 while (p != -1
and states_[
static_cast<size_t>(p)].next[c] == -1)
639 p =
states_[
static_cast<size_t>(p)].link;
646 if (
const int q =
states_[
static_cast<size_t>(p)].next[c];
647 states_[
static_cast<size_t>(p)].len + 1 ==
states_[
static_cast<size_t>(q)].len)
651 const int clone =
static_cast<int>(
states_.size());
656 states_[
static_cast<size_t>(clone)].len =
states_[
static_cast<size_t>(p)].
len + 1;
657 states_[
static_cast<size_t>(clone)].terminal =
false;
659 if (
states_[
static_cast<size_t>(clone)].link == -1)
660 states_[
static_cast<size_t>(clone)].link = 0;
662 while (p != -1
and states_[
static_cast<size_t>(p)].next[c] == q)
665 p =
states_[
static_cast<size_t>(p)].link;
668 states_[
static_cast<size_t>(q)].link = clone;
669 states_[
static_cast<size_t>(
cur)].link = clone;
682 void build(
const std::string_view text)
685 for (
const char c : text)
701 for (
const unsigned char c : pattern)
703 state =
states_[
static_cast<size_t>(state)].
next[c];
720 for (
size_t i = 1; i <
states_.size(); ++i)
746 for (
size_t i = 0; i <
other.size(); ++i)
748 const auto c =
static_cast<unsigned char>(
other[i]);
750 while (state != 0
and states_[
static_cast<size_t>(state)].next[c] == -1)
752 state =
states_[
static_cast<size_t>(state)].link;
753 len =
states_[
static_cast<size_t>(state)].len;
756 if (
states_[
static_cast<size_t>(state)].next[c] != -1)
758 state =
states_[
static_cast<size_t>(state)].
next[c];
821 return sam.longest_common_substring(b);
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error()
Throws std::domain_error unconditionally.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
size_t size_t int32_t * out
Simple dynamic array with automatic resizing and functional operations.
static Array create(size_t n)
Create an array with n logical elements.
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
constexpr bool is_empty() const noexcept
Checks if the container is empty.
T & append(const T &data)
Append a copy of data
void reserve(size_t cap)
Reserves cap cells into the array.
Naive compressed suffix tree (didactic implementation).
Array< size_t > find_all(const std::string_view pattern) const
Return all occurrences of a pattern.
void replace_child(const size_t parent, const size_t old_child, const size_t new_child)
Naive_Suffix_Tree(const std::string_view text="")
Construct a naive suffix tree.
static constexpr size_t npos
size_t node_count() const noexcept
Return the number of nodes in the tree.
size_t create_node(const size_t start, const size_t end, const size_t parent, const size_t suffix_index)
size_t find_child_by_first_char(const size_t node, const char c) const
void build(const std::string_view text)
Build or rebuild the suffix tree for text.
size_t text_size() const noexcept
Return the text size (without terminal marker).
void insert_suffix(const size_t suffix_start)
void collect_leaf_suffixes(const size_t node, Array< size_t > &out) const
bool contains(const std::string_view pattern) const
Return true if the pattern appears in the text.
static char choose_terminal(const std::string_view s)
const Array< Node > & nodes() const noexcept
Return the internal node array for inspection/debugging.
Suffix automaton (SAM) over byte alphabet.
std::string longest_common_substring(const std::string_view other) const
Find the longest common substring between the built SAM text and other.
void build(const std::string_view text)
Build the SAM from an entire string.
bool contains(const std::string_view pattern) const
Return true if pattern is a substring of the built text.
const Array< State > & states() const noexcept
Access the internal states array for testing/inspection.
void mark_terminals()
Traverse suffix links from last and mark all states as terminal.
size_t distinct_substring_count() const
Count the number of distinct substrings in the built text.
Suffix_Automaton()
Construct an empty suffix automaton (SAM) with only the root state.
size_t state_count() const noexcept
Return the number of states in the SAM.
void clear()
Reset the automaton to its initial empty state (root only).
void extend(const char ch)
Extend the SAM with a single character.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Array< size_t > all_positions(const size_t n)
Generate an array of all positions from 0 to n.
void sort_matches(Array< size_t > &a)
Sort matches in place using introsort.
Main namespace for Aleph-w library functions.
and std::convertible_to< std::invoke_result_t< const KeyFn &, size_t >, int > void counting_sort_indices(Array< size_t > &sa, Array< size_t > &tmp, const size_t n, const int min_key, const int max_key, const KeyFn &key_of)
Stable counting sort on an index array by integer keys.
Array< size_t > lcp_array_kasai(const std::string_view text, const Array< size_t > &sa)
Compute LCP array from text and suffix array using Kasai.
and
Check uniqueness with explicit hash + equality functors.
std::string longest_common_substring_sam(const std::string_view a, const std::string_view b)
Convenience function: LCS via suffix automaton.
std::vector< std::string > & split(const std::string &s, const char delim, std::vector< std::string > &elems)
Split a std::string by a single delimiter character.
void next()
Advance all underlying iterators (bounds-checked).
void introsort(T *a, const long l, const long r, const Compare &cmp=Compare())
Sort an array using introsort (introspective sort).
Array< size_t > suffix_array(const std::string_view text)
Build suffix array with doubling algorithm.
size_t parent
Parent node index.
size_t start
Start index in text.
size_t end
End index in text.
Array< size_t > children
Indices of children nodes.
size_t suffix_index
Index of suffix starting at leaf.
bool terminal
true if state is terminal
std::array< int, 256 > next
Transitions for each byte.
size_t first_pos
First occurrence end position.
size_t len
Max length of substring in this state.
Dynamic array container with automatic resizing.
Comprehensive sorting algorithms and search utilities for Aleph-w.