124template <
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T = GeometricRank,
unsigned CHAR_SIZE_BITS = sizeof(CHAR_T) * 8>
132 using LCP_T = std::conditional_t<MEMORY_EFFICIENT, MemoryEfficientLCP, unsigned>;
326 static constexpr unsigned NULLPTR = std::numeric_limits<unsigned>::max();
362 unsigned left = NULLPTR;
364 unsigned right = NULLPTR;
406 template <
typename CompareFunction>
432 template<
typename CompareFunction>
478 std::optional<ComparisonResult> k_compare_prefix_check(
492 inline LCP_T convert_lcp(
size_t val)
const noexcept;
518 inline ComparisonResult
k_compare(
const KEY_T* x,
const Bucket&
v,
const AncestorLCPs& ancestor_lcps)
const noexcept;
557template<
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
559 : _root_index(NULLPTR),
568template<
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
572 return search(key).contains;
575template<
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
579 return search(key).max_lcp;
582template<
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
635template<
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
640 return get_memory_efficient_lcp(
val);
648template<
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
670template<
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
678 return this->k_compare(
k,
v, ancestor_lcps);
685template<
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
686template<
typename CompareFunction>
690 if (_root_index == NULLPTR)
693 return {
false, {}, -1 };
696 unsigned v_index = _root_index;
710 if (comparison == std::strong_ordering::equal)
713 return {
true, lcp, depth };
717 if (comparison == std::strong_ordering::less)
742template <
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
747 _buckets.push_back({ key, RANK_T::get_random() });
754 return this->k_compare(
k,
v, ancestor_lcps);
764template <
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
765template<
typename CompareFunction>
772 x->ancestor_lcps = ancestor_lcps;
785 if (comparison == std::strong_ordering::equal)
793 if (
x_index == _buckets.size() - 1) {
801 if (comparison == std::strong_ordering::less)
816 v_node.ancestor_lcps.predecessor = lcp;
818 x->ancestor_lcps = ancestor_lcps;
841 v_node.ancestor_lcps.successor = lcp;
842 x->ancestor_lcps = ancestor_lcps;
856template<
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
863 return _buckets.size();
866template <
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
870 return height(_root_index);
873template <
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
887template <
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
892 return search(key).depth;
895template <
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
911template <
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
924 return depth + get_total_depth(_buckets[
node_index].left, depth + 1) + get_total_depth(_buckets[
node_index].right, depth + 1);
927template <
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
931 if (
num < _log_max_size)
945template <
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
952 std::cerr <<
"Error: Could not open file " <<
file_path <<
" for writing." << std::endl;
956 os <<
"digraph G {\n";
958 os <<
"\tnode [shape=record, fontname=\"Arial\"];\n";
960 os <<
"\tedge [fontname=\"Arial\"];\n";
962 if (_root_index != NULLPTR) {
963 to_dot_recursive(
os, _root_index);
965 os <<
"\tlabel=\"Empty Trie\";\n";
972template <
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
991 <<
"|Key: " << *node.
key
992 <<
"|Rank: (" <<
static_cast<unsigned>(node.
rank.geometric_rank) <<
"," <<
static_cast<unsigned>(node.
rank.uniform_rank) <<
")"
996 if (node.
left != NULLPTR)
1000 os <<
"\tnode_" <<
node_index <<
" -> node_" << node.
left <<
" [label=\" L\"];\n";
1002 to_dot_recursive(
os, node.
left);
1014 if (node.
right != NULLPTR)
1018 os <<
"\tnode_" <<
node_index <<
" -> node_" << node.
right <<
" [label=\" R\"];\n";
1020 to_dot_recursive(
os, node.
right);
1030template <
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
1035 return _buckets[_root_index].rank;
1038template <
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
1044template <
typename CHAR_T,
bool MEMORY_EFFICIENT,
typename RANK_T,
unsigned CHAR_SIZE_BITS>
1065 return os <<
"2^" <<
static_cast<unsigned>(
exp_of_2) <<
"*" <<
static_cast<unsigned>(
multiple);
1087 static std::random_device
rd;
1088 static std::default_random_engine
generator(
rd());
1090 static std::geometric_distribution<uint8_t>
g_dist(0.5);
1091 static std::uniform_int_distribution<uint8_t>
u_dist(0, std::numeric_limits<uint8_t>::max());
Defines the BitString class for compact character string storage and comparison.
A class to store strings compactly into integers, packing multiple characters into a single word.
typename ZT::Bucket Bucket
Alias for the Bucket (node) struct from the base class ZipTrie.
typename ZT::SearchResults SearchResults
Removes a node with a given key from the zip tree. (Not implemented)
typename ZT::LCP_T LCP_T
Alias for the LCP type used, inherited from the base class (ZipTrie::LCP_T).
typename ZT::KEY_T KEY_T
Alias for the Key type used, inherited from the base class (ZipTrie::KEY_T).
typename ZT::AncestorLCPs AncestorLCPs
Alias for the AncestorLCPs struct from the base class ZipTrie.
Implements a zip trie, a data structure combining properties of tries and zip trees for storing strin...
ZipTrie(unsigned max_size, unsigned max_lcp_length) noexcept
Constructs an empty ZipTrie.
const RANK_T & get_root_rank() const noexcept
Removes a node with a given key from the zip tree. (Not implemented)
int height() const noexcept
Calculates the height of the trie.
std::optional< ComparisonResult > k_compare_prefix_check(const Bucket &v, const AncestorLCPs &ancestor_lcps, size_t &out_start_lcp_val) const noexcept
Performs an initial check based on ancestor LCPs before full key comparison (k-compare optimization).
void set_root_index(unsigned root_index) noexcept
Directly sets the root index of the trie.
unsigned insert_recursive(Bucket *x, unsigned x_index, unsigned v_index, AncestorLCPs ancestor_lcps, CompareFunction compare_func) noexcept
Recursive helper function for inserting a new node x.
void to_dot_recursive(std::ofstream &os, unsigned node_index) const noexcept
Recursive helper function to generate the DOT language representation for a subtree.
ComparisonResult k_compare(const KEY_T *x, const Bucket &v, const AncestorLCPs &ancestor_lcps) const noexcept
Compares a key x with the key in a node v, utilizing ancestor LCPs for optimization (k-compare).
int height(unsigned node_index) const noexcept
Recursive helper function to calculate the height of the subtree rooted at node_index.
LCP_T convert_lcp(size_t val) const noexcept
Converts an exact LCP length (e.g., number of matching characters/bits) to the LCP_T type.
std::vector< Bucket > _buckets
A contiguous vector storing all the nodes (Buckets) of the trie.
void insert(const KEY_T *key) noexcept
Inserts a key into the zip trie.
bool contains(const KEY_T *key) const noexcept
Checks if a key exists within the trie.
MemoryEfficientLCP get_memory_efficient_lcp(size_t num) const noexcept
Converts a standard LCP length (size_t) into the MemoryEfficientLCP format.
void set(const KEY_T *key, RANK_T rank, unsigned left, unsigned right, LCP_T predecessor_lcp, LCP_T successor_lcp) noexcept
Directly adds a pre-constructed bucket to the internal storage vector.
void to_dot(const std::string &file_path) const noexcept
Generates a DOT language representation of the trie structure for visualization.
uint8_t _log_max_size
Stores the approximate log base 2 of the max_size provided during construction.
unsigned _root_index
Index of the root node within the _buckets vector. Initialized to NULLPTR for an empty trie.
std::conditional_t< MEMORY_EFFICIENT, MemoryEfficientLCP, unsigned > LCP_T
The type used to store Longest Common Prefix values.
unsigned _max_lcp_length
Stores the maximum possible LCP length provided during construction.
SearchResults search_recursive(const KEY_T *key, CompareFunction compare_func) const noexcept
Recursive helper function for the public search method.
uint64_t get_total_depth(unsigned node_index, uint64_t depth) const noexcept
Recursive helper function to calculate the sum of the depths of all nodes within a subtree.
int get_depth(const KEY_T *key) const noexcept
Calculates the depth of a given key in the trie.
LCP_T lcp(const KEY_T *key) const noexcept
Finds the Longest Common Prefix (LCP) between the search key and the path taken in the trie.
double get_average_height() const noexcept
Calculates the average depth of all nodes currently in the trie.
virtual SearchResults search(const KEY_T *key) const noexcept
Performs a search for a key within the ZipTrie.
unsigned size() const noexcept
Returns the number of nodes (keys) currently stored in the trie.
T * alloc_to_device(size_t size)
Allocates memory on the CUDA device.
Represents a rank used in zip-zip trees, typically generated randomly for balancing.
uint8_t geometric_rank
Rank component following a geometric distribution (primary rank). Higher values are less likely.
std::ostream & operator<<(std::ostream &os, const GeometricRank &rank)
Overloaded stream insertion operator (<<) for GeometricRank.
static GeometricRank get_random()
Generates a random rank using static random number generators.
auto operator<=>(const GeometricRank &) const =default
Default comparison operator.
uint8_t uniform_rank
Rank component following a uniform distribution (used for tie-breaking).
Represents an approximate Longest Common Prefix (LCP) length in a memory-efficient format.
auto operator<=>(const MemoryEfficientLCP &) const =default
Default comparison operator.
std::ostream & operator<<(std::ostream &os, const MemoryEfficientLCP &lcp)
Overloaded stream insertion operator (<<) for MemoryEfficientLCP.
std::ostream & print(std::ostream &os) const noexcept
Prints the LCP representation (e.g., "2^3 * 5") to an output stream.
uint8_t multiple
The multiple (mantissa) part of the LCP representation.
uint8_t exp_of_2
The exponent part of the LCP representation (base 2).
unsigned value() const noexcept
Calculates the approximate actual LCP value represented by this struct.
Stores the Longest Common Prefix (LCP) values associated with the path from the root down to a node's...
LCP_T successor
LCP accumulated along the path corresponding to the inorder successor branch.
LCP_T predecessor
LCP accumulated along the path corresponding to the inorder predecessor branch.
Represents a single node (bucket) within the ZipTrie's internal storage.
const KEY_T * key
Pointer to the key associated with this node.
AncestorLCPs ancestor_lcps
Stores the AncestorLCPs passed down from the parent during this node's insertion.
unsigned left
Index of the left child in the _buckets vector, or NULLPTR if no left child.
RANK_T rank
The rank associated with this node, used for maintaining the Zip Tree (max-heap) property.
unsigned right
Index of the right child in the _buckets vector, or NULLPTR if no right child.
Holds the result of comparing a search/insert key x with a node v's key, considering the context of a...
LCP_T lcp
The Longest Common Prefix (LCP) calculated between x and v during this specific comparison.
std::strong_ordering comparison
The relative ordering of x compared to v (std::strong_ordering::less, greater, or equal).
Holds the results returned by a search operation (search method).
LCP_T max_lcp
The Longest Common Prefix (LCP) calculated during the search.
int depth
The depth at which the key was found (number of edges from the root, root is depth 0).
bool contains
True if a node with the exact key was found in the trie, false otherwise.