Advertisement
maxim_shlyahtin

Aho-Korasik_2

Aug 7th, 2024
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.35 KB | None | 0 0
  1. #include <iostream>
  2. #include <map>
  3. #include <vector>
  4. #include <string>
  5. #include <array>
  6. #include <utility>
  7. #include <algorithm>
  8.  
  9. const int N = 5;
  10. const char WILDCARD = '?';
  11.  
  12. std::vector<std::string> patterns;
  13. std::array<char, N> alphabet = { 'A', 'C', 'T', 'G', 'N' };
  14.  
  15. struct Node {
  16.     std::map<char, Node*> son;
  17.     std::map<char, Node*> go;
  18.     Node* parent;
  19.     Node* suffLink;
  20.     Node* up;
  21.     char charToParent;
  22.     bool isTerminal;
  23.     std::vector<int> leafPatternNumber;
  24.  
  25.     Node() {
  26.         son = { {alphabet[0], NULL}, {alphabet[1], NULL}, {alphabet[2], NULL}, {alphabet[3], NULL}, {alphabet[4], NULL}, };
  27.         go = { {alphabet[0], NULL}, {alphabet[1], NULL}, {alphabet[2], NULL}, {alphabet[3], NULL}, {alphabet[4], NULL}, };
  28.         parent = nullptr;
  29.         suffLink = nullptr;
  30.         up = nullptr;
  31.         charToParent = ' ';
  32.         isTerminal = false;
  33.     }
  34. };
  35.  
  36. struct Trie {
  37.     Node* root;
  38.  
  39.     Trie() {
  40.         root = new Node();
  41.     }
  42.  
  43.     Node* getSuffLink(Node* v) {
  44.         if (v->suffLink == nullptr) {
  45.             if (v == root || v->parent == root) {
  46.                 v->suffLink = root;
  47.             }
  48.             else {
  49.                 v->suffLink = getLink(getSuffLink(v->parent), v->charToParent);
  50.             }
  51.         }
  52.         return v->suffLink;
  53.     }
  54.  
  55.     Node* getLink(Node* v, char c) {
  56.         if (v->go[c] == nullptr) {
  57.             if (v->son[c]) {
  58.                 v->go[c] = v->son[c];
  59.             }
  60.             else if (v == root) {
  61.                 v->go[c] = root;
  62.             }
  63.             else {
  64.                 v->go[c] = getLink(getSuffLink(v), c);
  65.             }
  66.         }
  67.         return v->go[c];
  68.     }
  69.  
  70.     Node* getUp(Node* v) {
  71.         if (v->up == nullptr) {
  72.             if (getSuffLink(v)->isTerminal) {
  73.                 v->up = getSuffLink(v);
  74.             }
  75.             else if (getSuffLink(v) == root) {
  76.                 v->up = root;
  77.             }
  78.             else {
  79.                 v->up = getUp(getSuffLink(v));
  80.             }
  81.         }
  82.         return v->up;
  83.     }
  84.  
  85.     void addString(const std::string& s, int patternNumber) {
  86.         Node* curr = root;
  87.         for (char c : s) {
  88.             if (curr->son[c] == nullptr) {
  89.                 curr->son[c] = new Node();
  90.                 curr->son[c]->parent = curr;
  91.                 curr->son[c]->charToParent = c;
  92.             }
  93.             curr = curr->son[c];
  94.         }
  95.         curr->isTerminal = true;
  96.         curr->leafPatternNumber.push_back(patternNumber);
  97.     }
  98.  
  99.     void processText(const std::string& text, std::vector<std::pair<int, int>>& results) {
  100.         Node* curr = root;
  101.         for (size_t i = 0; i < text.length(); ++i) {
  102.             char c = text[i];
  103.             curr = getLink(curr, c);
  104.             Node* checkNode = curr;
  105.             while (checkNode != root) {
  106.                 if (checkNode->isTerminal) {
  107.                     for (int patNum : checkNode->leafPatternNumber) {
  108.                         results.push_back({ i + 2 - patterns[patNum].length(), patNum + 1 });
  109.                     }
  110.                 }
  111.                 checkNode = getUp(checkNode);
  112.             }
  113.         }
  114.     }
  115. };
  116.  
  117. std::vector<int> findPatternWithWildcards(const std::string& text, const std::string& pattern, char wildcard) {
  118.     std::vector<std::string> subPatterns;
  119.     std::vector<int> startPositions;
  120.     std::string currentSubPattern;
  121.     for (size_t i = 0; i < pattern.length(); ++i) {
  122.         if (pattern[i] == wildcard) {
  123.             if (!currentSubPattern.empty()) {
  124.                 subPatterns.push_back(currentSubPattern);
  125.                 startPositions.push_back(i - currentSubPattern.length() + 1);
  126.                 currentSubPattern.clear();
  127.             }
  128.         }
  129.         else {
  130.             currentSubPattern += pattern[i];
  131.         }
  132.     }
  133.     if (!currentSubPattern.empty()) {
  134.         subPatterns.push_back(currentSubPattern);
  135.         startPositions.push_back(pattern.length() - currentSubPattern.length() + 1);
  136.     }
  137.  
  138.     Trie trie;
  139.     for (size_t i = 0; i < subPatterns.size(); ++i) {
  140.         trie.addString(subPatterns[i], i);
  141.     }
  142.  
  143.     /*for (const auto& it : subPatterns) {
  144.         std::cout << it << ' ';
  145.     }
  146.  
  147.     std::cout << '\n';
  148.  
  149.     for (const auto& it : startPositions) {
  150.         std::cout << it << ' ';
  151.     }
  152.  
  153.     std::cout << '\n';*/
  154.  
  155.     for (const auto& it : subPatterns) {
  156.         patterns.push_back(it);
  157.     }
  158.  
  159.     std::vector<std::pair<int, int>> results;
  160.     trie.processText(text, results);
  161.  
  162.     std::vector<int> C(text.length(), 0);
  163.     for (const auto& result : results) {
  164.         int pos = result.first - startPositions[result.second - 1];
  165.         if (pos >= 0 && pos + pattern.length() <= text.length()) {
  166.             C[pos]++;
  167.         }
  168.     }
  169.  
  170.     std::vector<int> finalPositions;
  171.     for (size_t i = 0; i < C.size(); ++i) {
  172.         if (C[i] == subPatterns.size()) {
  173.             finalPositions.push_back(i);
  174.         }
  175.     }
  176.  
  177.     return finalPositions;
  178. }
  179.  
  180. int main() {
  181.     std::string text;
  182.     std::string pattern;
  183.     char wildcard;
  184.  
  185.     std::cin >> text;
  186.     std::cin >> pattern;
  187.     std::cin >> wildcard;
  188.  
  189.     std::vector<int> positions = findPatternWithWildcards(text, pattern, wildcard);
  190.     std::sort(positions.begin(), positions.end());
  191.     for (int pos : positions) {
  192.         std::cout << pos + 1 << "\n";
  193.     }
  194.  
  195.     return 0;
  196. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement