Advertisement
Guest User

Untitled

a guest
Dec 8th, 2019
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.78 KB | None | 0 0
  1. /*
  2.     B. Two suffix tree
  3.     Äàíû ñòðîêè s è t. Ïîñòðîéòå ñæàòîå ñóôôèêñíîå äåðåâî, êîòîðîå ñîäåðæèò âñå ñóôôèêñû ñòðîêè s è ñòðîêè t.
  4.     Íàéäèòå òàêîå äåðåâî, êîòîðîå ñîäåðæèò ìèíèìàëüíîå êîëè÷åñòâî âåðøèí.
  5. */
  6.  
  7.  
  8. #include <iostream>
  9. #include <vector>
  10. #include <string>
  11. #include <map>
  12.  
  13. class SuffTreeBuilder {
  14. public:
  15.     struct Node {
  16.     public:
  17.         std::map<char, Node*> children;
  18.  
  19.         Node(int start, int* end, Node* root) :
  20.             start(start), end(end),
  21.             suffix_link(root), children() {}
  22.  
  23.         int get_end() { return (*end); }
  24.         int get_start() { return start; };
  25.         void add_to_start(int length) { start += length; }
  26.         int get_length() { return *(end)-(start) + 1; }
  27.  
  28.         bool has_next(char c);
  29.         Node* get_next(char c);
  30.  
  31.         void add_child(char c, Node* node);
  32.  
  33.         Node* get_suffix_link() { return suffix_link; }
  34.         void set_suffix_link(Node* node) { suffix_link = node; }
  35.  
  36.     private:
  37.         int start;
  38.         int *end;
  39.         Node* suffix_link;
  40.     };
  41.  
  42.     Node* root;
  43.    
  44.     SuffTreeBuilder(std::string& str, int first_str_len) :
  45.         root(nullptr), last_new_node(nullptr), active_node(nullptr),
  46.         active_edge(-1), active_length(0), remainder(0),
  47.         leaf_end(-1), split_end(nullptr), str(str), size(1),
  48.         first_str_len(first_str_len)
  49.     {
  50.         build_tree();
  51.     }
  52.  
  53.     void build_tree(); // to build
  54.  
  55.     void print_tree_and_size();
  56.     void print(Node* node, int& num_in_dfs, int parent_num);
  57. private:
  58.     Node* last_new_node;
  59.     Node* active_node;
  60.  
  61.     int active_edge;
  62.     int active_length;
  63.     int remainder;
  64.  
  65.     int leaf_end;
  66.     int* split_end;
  67.  
  68.     std::string str;
  69.  
  70.     // to get answer for the task
  71.     int size;
  72.     int first_str_len;
  73.  
  74.     void extend_tree(int pos);
  75. };
  76.  
  77. bool SuffTreeBuilder::Node::has_next(char c) {
  78.     if (children.find(c) != children.end()) {
  79.         return true;
  80.     }
  81.     return false;
  82. }
  83.  
  84. SuffTreeBuilder::Node* SuffTreeBuilder::Node::get_next(char c) {
  85.     auto it = children.find(c);
  86.     return it->second;
  87. }
  88.  
  89. void SuffTreeBuilder::Node::add_child(char c, Node* node) {
  90.     auto it = children.find(c);
  91.     if (it == children.end()) {
  92.         children.insert(std::make_pair(c, node));
  93.     }
  94.     else {
  95.         it->second = node; //rewrite if needed
  96.     }
  97. }
  98.  
  99. void SuffTreeBuilder::build_tree() { // Ukkonen's algorithm
  100.     int length = str.length();
  101.     int* root_end = new int;
  102.     *root_end = -1;
  103.  
  104.     root = new Node(-1, root_end, root);
  105.  
  106.     active_node = root;
  107.     for (int i = 0; i < length; i++) {
  108.         extend_tree(i);
  109.     }
  110. }
  111.  
  112. void SuffTreeBuilder::extend_tree(int pos) {
  113.     last_new_node = nullptr;
  114.     leaf_end = pos;
  115.  
  116.     ++remainder;
  117.     while (remainder > 0) {
  118.  
  119.         if (active_length == 0) {
  120.             active_edge = pos;
  121.         }
  122.  
  123.         if (active_node->has_next(str[active_edge])) {
  124.             Node* next = active_node->get_next(str[active_edge]); // go to this node
  125.  
  126.             int next_len = next->get_length();
  127.             if (active_length >= next_len) { //if we need to go to the next node
  128.                 active_node = next;
  129.  
  130.                 active_length -= next_len;
  131.                 active_edge += next_len;
  132.                 continue;
  133.             }
  134.  
  135.             int pos_in = next->get_start() + active_length;
  136.             if (str[pos_in] == str[pos]) {
  137.                 if (last_new_node != nullptr && active_node != root) { //set suffix link
  138.                     last_new_node->set_suffix_link(active_node);
  139.                     last_new_node = nullptr;
  140.                 }
  141.                 ++active_length; // we just need to remember new length
  142.                 break;
  143.             }
  144.  
  145.             // if active_pointer is on the edge, we need to split for new node
  146.  
  147.             int* split_end = new int;
  148.             *split_end = pos_in - 1;
  149.  
  150.             ++size;
  151.             Node* new_node = new Node(next->get_start(), split_end, root);
  152.             active_node->add_child(str[next->get_start()], new_node);
  153.  
  154.             // create new leaf
  155.             ++size;
  156.             Node* new_leaf = new Node(pos, &leaf_end, root);
  157.             new_node->add_child(str[pos], new_leaf);
  158.             next->add_to_start(active_length);
  159.             new_node->children[str[next->get_start()]] = next;
  160.  
  161.             if (last_new_node != nullptr) {
  162.                 last_new_node->set_suffix_link(new_node);
  163.             }
  164.  
  165.             last_new_node = new_node;
  166.         } else {
  167.             ++size;
  168.             Node* new_leaf = new Node(pos, &leaf_end, root); // new leaf
  169.             active_node->add_child(str[active_edge], new_leaf);
  170.  
  171.             if (last_new_node != nullptr) { // set suffix link from previous step
  172.                 last_new_node->set_suffix_link(active_node);
  173.                 last_new_node = nullptr;
  174.             }
  175.         }
  176.  
  177.         --remainder;
  178.  
  179.         if (active_node == root && active_length > 0) {
  180.             --active_length;
  181.             active_edge = pos - remainder + 1; // new edge
  182.         }
  183.         else if (active_node != root) {
  184.             active_node = active_node->get_suffix_link(); // go to suffix_link
  185.         }
  186.     }
  187. }
  188.  
  189. void SuffTreeBuilder::print(Node* node, int& num_in_dfs, int parent_num) {
  190.     if (node->get_start() < first_str_len) {
  191.         if (node->get_end() < first_str_len) {
  192.             printf("%d %d %d %d\n", parent_num, 0, node->get_start(), node->get_end() + 1);
  193.         } else {
  194.             printf("%d %d %d %d\n", parent_num, 0, node->get_start(), first_str_len);
  195.         }
  196.     } else {
  197.         printf("%d %d %d %d\n", parent_num, 1, node->get_start() - first_str_len, node->get_end() + 1 - first_str_len);
  198.     }
  199.  
  200.     if (node->children.size() == 0) { // if it's a leaf node
  201.         return;
  202.     }
  203.  
  204.     parent_num = num_in_dfs;
  205.     for (auto it = node->children.begin(); it != node->children.end(); ++it) { // go in children
  206.         ++num_in_dfs;
  207.         print(it->second, num_in_dfs, parent_num);
  208.     }
  209. }
  210.  
  211. void SuffTreeBuilder::print_tree_and_size() {
  212.     printf("%d\n", size); // printf for faster print
  213.     int num_in_dfs = 0;
  214.     for (auto it = root->children.begin(); it != root->children.end(); ++it) {
  215.         ++num_in_dfs;
  216.         print(it->second, num_in_dfs, 0); // go in children
  217.     }
  218. }
  219.  
  220. int main() {
  221.  
  222.     std::string str1;
  223.     std::string str2;
  224.     std::cin >> str1 >> str2;
  225.  
  226.     str1 += str2;
  227.  
  228.     SuffTreeBuilder* suff_tree_builder = new SuffTreeBuilder(str1, str1.length() - str2.length());
  229.  
  230.     suff_tree_builder->print_tree_and_size();
  231.  
  232.     return 0;
  233. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement