Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- B. Two suffix tree
- Äàíû ñòðîêè s è t. Ïîñòðîéòå ñæàòîå ñóôôèêñíîå äåðåâî, êîòîðîå ñîäåðæèò âñå ñóôôèêñû ñòðîêè s è ñòðîêè t.
- Íàéäèòå òàêîå äåðåâî, êîòîðîå ñîäåðæèò ìèíèìàëüíîå êîëè÷åñòâî âåðøèí.
- */
- #include <iostream>
- #include <vector>
- #include <string>
- #include <map>
- class SuffTreeBuilder {
- public:
- struct Node {
- public:
- std::map<char, Node*> children;
- Node(int start, int* end, Node* root) :
- start(start), end(end),
- suffix_link(root), children() {}
- int get_end() { return (*end); }
- int get_start() { return start; };
- void add_to_start(int length) { start += length; }
- int get_length() { return *(end)-(start) + 1; }
- bool has_next(char c);
- Node* get_next(char c);
- void add_child(char c, Node* node);
- Node* get_suffix_link() { return suffix_link; }
- void set_suffix_link(Node* node) { suffix_link = node; }
- private:
- int start;
- int *end;
- Node* suffix_link;
- };
- Node* root;
- SuffTreeBuilder(std::string& str, int first_str_len) :
- root(nullptr), last_new_node(nullptr), active_node(nullptr),
- active_edge(-1), active_length(0), remainder(0),
- leaf_end(-1), split_end(nullptr), str(str), size(1),
- first_str_len(first_str_len)
- {
- build_tree();
- }
- void build_tree(); // to build
- void print_tree_and_size();
- void print(Node* node, int& num_in_dfs, int parent_num);
- private:
- Node* last_new_node;
- Node* active_node;
- int active_edge;
- int active_length;
- int remainder;
- int leaf_end;
- int* split_end;
- std::string str;
- // to get answer for the task
- int size;
- int first_str_len;
- void extend_tree(int pos);
- };
- bool SuffTreeBuilder::Node::has_next(char c) {
- if (children.find(c) != children.end()) {
- return true;
- }
- return false;
- }
- SuffTreeBuilder::Node* SuffTreeBuilder::Node::get_next(char c) {
- auto it = children.find(c);
- return it->second;
- }
- void SuffTreeBuilder::Node::add_child(char c, Node* node) {
- auto it = children.find(c);
- if (it == children.end()) {
- children.insert(std::make_pair(c, node));
- }
- else {
- it->second = node; //rewrite if needed
- }
- }
- void SuffTreeBuilder::build_tree() { // Ukkonen's algorithm
- int length = str.length();
- int* root_end = new int;
- *root_end = -1;
- root = new Node(-1, root_end, root);
- active_node = root;
- for (int i = 0; i < length; i++) {
- extend_tree(i);
- }
- }
- void SuffTreeBuilder::extend_tree(int pos) {
- last_new_node = nullptr;
- leaf_end = pos;
- ++remainder;
- while (remainder > 0) {
- if (active_length == 0) {
- active_edge = pos;
- }
- if (active_node->has_next(str[active_edge])) {
- Node* next = active_node->get_next(str[active_edge]); // go to this node
- int next_len = next->get_length();
- if (active_length >= next_len) { //if we need to go to the next node
- active_node = next;
- active_length -= next_len;
- active_edge += next_len;
- continue;
- }
- int pos_in = next->get_start() + active_length;
- if (str[pos_in] == str[pos]) {
- if (last_new_node != nullptr && active_node != root) { //set suffix link
- last_new_node->set_suffix_link(active_node);
- last_new_node = nullptr;
- }
- ++active_length; // we just need to remember new length
- break;
- }
- // if active_pointer is on the edge, we need to split for new node
- int* split_end = new int;
- *split_end = pos_in - 1;
- ++size;
- Node* new_node = new Node(next->get_start(), split_end, root);
- active_node->add_child(str[next->get_start()], new_node);
- // create new leaf
- ++size;
- Node* new_leaf = new Node(pos, &leaf_end, root);
- new_node->add_child(str[pos], new_leaf);
- next->add_to_start(active_length);
- new_node->children[str[next->get_start()]] = next;
- if (last_new_node != nullptr) {
- last_new_node->set_suffix_link(new_node);
- }
- last_new_node = new_node;
- } else {
- ++size;
- Node* new_leaf = new Node(pos, &leaf_end, root); // new leaf
- active_node->add_child(str[active_edge], new_leaf);
- if (last_new_node != nullptr) { // set suffix link from previous step
- last_new_node->set_suffix_link(active_node);
- last_new_node = nullptr;
- }
- }
- --remainder;
- if (active_node == root && active_length > 0) {
- --active_length;
- active_edge = pos - remainder + 1; // new edge
- }
- else if (active_node != root) {
- active_node = active_node->get_suffix_link(); // go to suffix_link
- }
- }
- }
- void SuffTreeBuilder::print(Node* node, int& num_in_dfs, int parent_num) {
- if (node->get_start() < first_str_len) {
- if (node->get_end() < first_str_len) {
- printf("%d %d %d %d\n", parent_num, 0, node->get_start(), node->get_end() + 1);
- } else {
- printf("%d %d %d %d\n", parent_num, 0, node->get_start(), first_str_len);
- }
- } else {
- printf("%d %d %d %d\n", parent_num, 1, node->get_start() - first_str_len, node->get_end() + 1 - first_str_len);
- }
- if (node->children.size() == 0) { // if it's a leaf node
- return;
- }
- parent_num = num_in_dfs;
- for (auto it = node->children.begin(); it != node->children.end(); ++it) { // go in children
- ++num_in_dfs;
- print(it->second, num_in_dfs, parent_num);
- }
- }
- void SuffTreeBuilder::print_tree_and_size() {
- printf("%d\n", size); // printf for faster print
- int num_in_dfs = 0;
- for (auto it = root->children.begin(); it != root->children.end(); ++it) {
- ++num_in_dfs;
- print(it->second, num_in_dfs, 0); // go in children
- }
- }
- int main() {
- std::string str1;
- std::string str2;
- std::cin >> str1 >> str2;
- str1 += str2;
- SuffTreeBuilder* suff_tree_builder = new SuffTreeBuilder(str1, str1.length() - str2.length());
- suff_tree_builder->print_tree_and_size();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement