vadimk772336

file last

Mar 19th, 2022
1,253
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.93 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <fstream>
  5. using namespace std;
  6. ofstream out("results.txt");
  7.  
  8. struct vertex
  9. {
  10.     int next[26];
  11.     int go[26];
  12.     int parent;
  13.     char parent_char;
  14.     int link;
  15.     int short_link;
  16.     std::vector<int> end_list;
  17.     bool is_terminal;
  18.    
  19. };
  20.  
  21. void clean_trie(vertex* trie, int size)
  22. {
  23.     for (int i = 0; i < size; ++i)
  24.     {
  25.         trie[i].is_terminal = false;
  26.         trie[i].parent = -1;
  27.         trie[i].link = -1;
  28.         trie[i].short_link = -1;
  29.         for (int j = 0; j < 26; ++j)
  30.         {
  31.             trie[i].next[j] = -1;
  32.             trie[i].go[j] = -1;
  33.         }
  34.     }
  35. }
  36.  
  37. void add_string(std::string s, int s_len, vertex* trie, int& size, int end_pos)
  38. {
  39.  
  40.     int v = 0;
  41.     int c_idx;
  42.     char c;
  43.  
  44.     for (int i = 0; i < s_len; ++i)
  45.     {
  46.         c = s[i];
  47.         c_idx = static_cast<int>(c) - 97;
  48.  
  49.         if (trie[v].next[c_idx] == -1)
  50.         {
  51.             trie[size].link = -1;
  52.             trie[size].short_link = -1;
  53.             trie[size].parent = v;
  54.             trie[size].parent_char = c;
  55.             trie[v].next[c_idx] = size++;
  56.         }
  57.  
  58.         v = trie[v].next[c_idx];
  59.     }
  60.     trie[v].is_terminal = true;
  61.     trie[v].end_list.push_back(end_pos);
  62. }
  63.  
  64. int get_link(int v, char c, vertex* trie);
  65.  
  66. int get_suff_link(int v, vertex* trie)
  67. {
  68.     if (trie[v].link == -1)
  69.     {
  70.         if (v == 0 || trie[v].parent == 0)
  71.             trie[v].link = 0;
  72.         else
  73.             trie[v].link = get_link(get_suff_link(trie[v].parent, trie), trie[v].parent_char, trie);
  74.     }
  75.     return trie[v].link;
  76. }
  77.  
  78. int get_link(int v, char c, vertex* trie)
  79. {
  80.  
  81.     int c_idx = static_cast<int>(c) - 97;
  82.  
  83.     if (trie[v].go[c_idx] == -1)
  84.     {
  85.         if (trie[v].next[c_idx] != -1)
  86.             trie[v].go[c_idx] = trie[v].next[c_idx];
  87.  
  88.         else if (v == 0)
  89.             trie[v].go[c_idx] = 0;
  90.  
  91.         else
  92.             trie[v].go[c_idx] = get_link(get_suff_link(v, trie), c, trie);
  93.     }
  94.  
  95.     return trie[v].go[c_idx];
  96. }
  97.  
  98. int get_short_link(int v, vertex* trie)
  99. {
  100.     if (trie[v].short_link == -1)
  101.     {
  102.         int u = get_suff_link(v, trie);
  103.         if (trie[u].is_terminal || u == 0)
  104.             trie[v].short_link = u;
  105.         else
  106.             trie[v].short_link = get_short_link(u, trie);
  107.     }
  108.  
  109.     return trie[v].short_link;
  110. }
  111.  
  112. void fill_trie(int p_len, std::string P, vertex* trie, int& trie_size, int& count_templates)
  113. {
  114.  
  115.     clean_trie(trie, 26 * p_len);
  116.  
  117.     int start = 0;
  118.     std::string mask;
  119.     int len_mask;
  120.     for (int i = 0; i < p_len; ++i)
  121.     {
  122.         if (P[i] == '?')
  123.         {
  124.             if (i - start > 0)
  125.             {
  126.                 len_mask = i - start;
  127.                 mask = P.substr(start, len_mask);
  128.                 add_string(mask, len_mask, trie, trie_size, i - 1);
  129.                 count_templates++;
  130.             }
  131.  
  132.             start = i + 1;
  133.         }
  134.     }
  135.    
  136.     if (P[p_len - 1] != '?')
  137.     {
  138.         len_mask = p_len - start;
  139.         mask = P.substr(start, len_mask);
  140.         add_string(mask, len_mask, trie, trie_size, p_len - 1);
  141.         count_templates++;
  142.     }
  143. }
  144.  
  145. void print_answer(int p_len, int t_len, int* C, int count_templates)
  146. {
  147.     int count_pos = 0;
  148.     std::vector<int> ans;
  149.     for (int i = 0; i < t_len; ++i)
  150.     {
  151.         if (C[i] == count_templates && i+p_len <= t_len)
  152.         {
  153.             count_pos++;
  154.             ans.push_back(i);
  155.         }
  156.     }
  157.    
  158.     out << count_pos << " ";
  159.     for (int i = 0; i < count_pos; ++i)
  160.         out << ans[i] << " ";
  161.    
  162. }
  163.  
  164. void search_pattern(int t_len, vertex* trie, std::string T, int& count_templates, int p_len)
  165. {
  166.  
  167.     int v = 0;
  168.     int u, idx;
  169.  
  170.     int C[t_len];
  171.     for (int i = 0; i < t_len; ++i)
  172.         C[i] = 0;
  173.  
  174.     for (int i = 0; i < t_len; ++i)
  175.     {
  176.         v = get_link(v, T[i], trie);
  177.        
  178.         u = v;
  179.         while (u > 0)
  180.         {
  181.             if (trie[u].is_terminal)
  182.             {
  183.                 for (int k = 0; k < trie[u].end_list.size(); ++k)
  184.                 {
  185.                     idx = i - trie[u].end_list[k];
  186.                     if (idx >= 0 && idx < t_len)
  187.                         C[idx]++;
  188.                 }
  189.             }
  190.             u = get_short_link(u, trie);
  191.         }
  192.     }
  193.  
  194.     print_answer(p_len, t_len, C, count_templates);
  195.    
  196. }
  197.  
  198. void f(std::string P, std::string T)
  199. {
  200.     int p_len = P.length();
  201.     int t_len = T.length();
  202.  
  203.  
  204.     int count_templates = 0;
  205.     int trie_size = 1;
  206.     vertex trie[p_len * 26 + 1];
  207.  
  208.     fill_trie(p_len, P, trie, trie_size, count_templates);
  209.  
  210.     search_pattern(t_len, trie, T, count_templates, p_len);
  211. }
  212.  
  213. int main()
  214. {
  215.  
  216.     int count_tests;
  217.     ifstream ifs("tests.txt");
  218.     ifs >> count_tests;
  219.    
  220.     for (int i = 0; i < count_tests; ++i)
  221.     {
  222.  
  223.         std::string P, T;
  224.         ifs >> P >> T;
  225.         f(P, T);
  226.        
  227.         out << "\n";
  228.     }
  229.  
  230.     return 0;
  231. }
  232.  
Advertisement
Add Comment
Please, Sign In to add comment