vadimk772336

2

Mar 18th, 2022 (edited)
417
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.92 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4. using namespace std;
  5.  
  6. struct vertex
  7. {
  8.     bool is_terminal;
  9.     int next[26];
  10.     int go[26];
  11.     int parent;
  12.     char parent_char;
  13.     int link;
  14.     int depth;
  15. };
  16.  
  17. void clean_trie(vertex* trie, int size)
  18. {
  19.     for (int i = 0; i < size; ++i)
  20.     {
  21.         trie[i].is_terminal = false;
  22.         trie[i].parent = -1;
  23.         trie[i].link = -1;
  24.         trie[i].depth = 0;
  25.         for (int j = 0; j < 26; ++j)
  26.         {
  27.             trie[i].next[j] = -1;
  28.             trie[i].go[j] = -1;
  29.         }
  30.     }
  31. }
  32.  
  33. void add_string(string s, int s_len, vertex* trie, int& size)
  34. {
  35.  
  36.     // cout << "add: " << s << endl;
  37.     int v = 0;
  38.     int c_idx;
  39.     vertex buff;
  40.     char c;
  41.  
  42.     for (int i = 0; i < s_len; ++i)
  43.     {
  44.         c = s[i];
  45.         c_idx = static_cast<int>(c) - 97;
  46.  
  47.         if (trie[v].next[c_idx] == -1)
  48.         {
  49.             trie[size].link = -1;
  50.             trie[size].parent = v;
  51.             trie[size].parent_char = c;
  52.             trie[v].next[c_idx] = size++;
  53.         }
  54.  
  55.         v = trie[v].next[c_idx];
  56.     }
  57.     trie[v].is_terminal = true;
  58.     trie[v].depth = s_len;
  59. }
  60.  
  61. int get_link(int v, char c, vertex* trie);
  62.  
  63. int get_suff_link(int v, vertex* trie)
  64. {
  65.     if (trie[v].link == -1)
  66.     {
  67.         if (v == 0 || trie[v].parent == 0)
  68.             trie[v].link = 0;
  69.         else
  70.             trie[v].link = get_link(get_suff_link(trie[v].parent, trie), trie[v].parent_char, trie);
  71.     }
  72.     return trie[v].link;
  73. }
  74.  
  75. int get_link(int v, char c, vertex* trie)
  76. {
  77.  
  78.     int c_idx = static_cast<int>(c) - 97;
  79.  
  80.     if (trie[v].go[c_idx] == -1)
  81.     {
  82.         if (trie[v].next[c_idx] != -1)
  83.             trie[v].go[c_idx] = trie[v].next[c_idx];
  84.  
  85.         else if (v == 0)
  86.             trie[v].go[c_idx] = 0;
  87.  
  88.         else
  89.             trie[v].go[c_idx] = get_link(get_suff_link(v, trie), c, trie);
  90.     }
  91.  
  92.     return trie[v].go[c_idx];
  93. }
  94.  
  95. void fill_trie(int p_len, string P, vertex* trie, int& trie_size)
  96. {
  97.  
  98.     clean_trie(trie, 26 * p_len);
  99.  
  100.     int i = 0;
  101.     int start = 0;
  102.     string mask;
  103.     int len_mask;
  104.     while (i < p_len)
  105.     {
  106.         if (P[i] == '?')
  107.         {
  108.             if (i - start > 0)
  109.             {
  110.                 len_mask = i - start;
  111.                 mask = P.substr(start, len_mask);
  112.                 add_string(mask, len_mask, trie, trie_size);
  113.             }
  114.  
  115.             start = i + 1;
  116.         }
  117.  
  118.         else if (i == p_len - 1)
  119.         {
  120.             len_mask = i - start + 1;
  121.             mask = P.substr(start, len_mask);
  122.             add_string(mask, len_mask, trie, trie_size);
  123.         }
  124.  
  125.         i++;
  126.     }
  127. }
  128.  
  129. void display(vertex* trie, int size, bool display_links)
  130. {
  131.     for (int i = 0; i < size; ++i)
  132.     {
  133.         bool flag = true;
  134.         for (int j = 0; j < 26; ++j)
  135.         {
  136.             if (trie[i].next[j] >= 0)
  137.             {
  138.                 if (flag)
  139.                 {
  140.                     if (trie[i].is_terminal)
  141.                         cout << "vertex " << i << ": (is_terminal) ";
  142.                     else
  143.                         cout << "vertex " << i << ": ";
  144.                     flag = false;
  145.                 }
  146.                 cout << char(j + 97) << "->" << trie[i].next[j] << " ";
  147.             }
  148.         }
  149.         if (not flag)
  150.             cout << endl;
  151.         if (flag && trie[i].is_terminal)
  152.             cout << "vertex " << i << ": (is_terminal);" << endl;
  153.     }
  154.  
  155.     if (display_links)
  156.     {
  157.         cout << "\n Ссылки:" << endl;
  158.         for (int v = 0; v < size; ++v)
  159.         {
  160.             cout << "vertex: " << v << "  ";
  161.             cout << "suff: " << get_suff_link(v, trie) << ";  ";
  162.             cout << "get_link: ";
  163.             for (int j = 0; j < 26; ++j)
  164.             {
  165.                 int z = get_link(v, char(j + 97), trie);
  166.                 if (z > 0)
  167.                     cout << "(" << char(j + 97) << "," << z << ") ";
  168.             }
  169.             cout << endl;
  170.         }
  171.     }
  172. }
  173.  
  174. void search_pattern(int t_len, vertex* trie, string T)
  175. {
  176.  
  177.     char c;
  178.     int v = 0;
  179.     int u;
  180.     int c_idx;
  181.     int start = 0;
  182.  
  183.     for (int i = 0; i < t_len; ++i)
  184.     {
  185.         c = T[i];
  186.         c_idx = static_cast<int>(c) - 97;
  187.  
  188.         cout << "\n Текущий символ: " << c << ", текущая вершина: " << v << endl;
  189.  
  190.         //Если нет пути
  191.         if (trie[v].next[c_idx] == -1)
  192.         {
  193.             cout << "Нет пути - прыгаем по суфф ссылкам из вершины " << v << endl;
  194.             //то прыгаем по суфф сылкам назад пока не найдем путь
  195.             while (v > 0 && trie[v].next[c_idx] == -1)
  196.             {
  197.                 v = get_suff_link(v, trie);
  198.                 cout << "прыгнул в " << v << "; ";
  199.             }
  200.             cout << endl;
  201.  
  202.             if (trie[v].next[c_idx] != -1)
  203.             {
  204.                 cout << "Нашли путь, переходим в вершину " << trie[v].next[c_idx] << endl;
  205.                 v = trie[v].next[c_idx];
  206.             }
  207.             else
  208.             {
  209.                 cout << "Путь не найден, сидим в корне, vertex: " << v << endl;
  210.             }
  211.         }
  212.         else
  213.         {
  214.             cout << "Путь есть, переходим по ребру в вершину " << trie[v].next[c_idx] << endl;
  215.             v = trie[v].next[c_idx];
  216.         }
  217.  
  218.         //если терминальная принтим и потом бежим по суфф ссылкам до корня в поисках других
  219.         //терминальных
  220.         if (trie[v].is_terminal)
  221.         {
  222.             cout << "Вершина " << v << " оказалась терминальной " << endl;
  223.             u = v;
  224.             cout << "Начинаю прыгать по суфф ссылкам: " << endl;
  225.             while (u > 0)
  226.             {
  227.                 if (trie[u].is_terminal)
  228.                 {
  229.                     cout << u << "- терминальная -  принтим: ";
  230.                     cout << "(" << i - trie[u].depth + 1 << "," << i << ")" << endl;
  231.                 }
  232.                 u = get_suff_link(u, trie);
  233.                 cout << "Прыгнул в " << u << endl;
  234.             }
  235.         }
  236.  
  237.         else
  238.             cout << "Не терминальная, ждём некст символ " << endl;
  239.         //если нет то просто ожидаем некст символ
  240.     }
  241. }
  242.  
  243.  
  244. int main()
  245. {
  246.  
  247.     string P, T;
  248.     // cin >> P >> T;
  249.     // P = "he?she?his?hers";
  250.     P = "";
  251.     // P = "abcd";
  252.     T = "sheyuihe";
  253.  
  254.     int p_len = P.length();
  255.     int t_len = T.length();
  256.  
  257.     int trie_size = 1;
  258.     int max_size = 26 * p_len;
  259.     vertex trie[max_size];
  260.  
  261.     fill_trie(p_len, P, trie, trie_size);
  262.  
  263.     // display(trie,max_size, false);
  264.  
  265.     search_pattern(t_len, trie, T);
  266.  
  267.  
  268.     return 0;
  269. }
  270.  
Add Comment
Please, Sign In to add comment