Advertisement
vadimk772336

34

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