Advertisement
Guest User

Untitled

a guest
Jul 30th, 2016
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.33 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. # include <iostream>
  3. # include <map>
  4. # include <vector>
  5. # include <string>
  6. # include <queue>
  7.  
  8. #include <unordered_map>
  9.  
  10. #include <boost/range/begin.hpp>
  11. #include <boost/range/end.hpp>
  12.  
  13. using namespace std;
  14.  
  15. template <typename T>
  16. class BorNode
  17. {
  18.  
  19. public:
  20.     typedef T value_type;
  21.     std::unordered_map<value_type, BorNode*> links;
  22.     BorNode *fail, *term;  // Предыдущее состояние для функции отката. Только для root равно NULL.
  23.     //BorNode *term; // Ближайшее терминальное состояние. Если отстутствует - NULL
  24.     bool out;
  25.  
  26. public:
  27.     BorNode(BorNode *fail_node = NULL)
  28.             : fail(fail_node)
  29.             , term(NULL)
  30.             , out(false)
  31.     { }
  32.  
  33.     BorNode* getLink(const char& c) const
  34.     {
  35.         auto iter = links.find(c);
  36.         if (iter != links.cend())
  37.         {
  38.             return iter->second;
  39.         }
  40.         else
  41.         {
  42.             return nullptr;
  43.         }
  44.     }
  45.  
  46.     bool isTerminal() const
  47.     {
  48.         return out;
  49.     }
  50. };
  51.  
  52.  
  53. template<typename T, typename Map, typename ResultCont = std::vector<std::vector<T>>>
  54. class AhoCorasick
  55. {
  56. public:
  57.     typedef void (*Callback) (const char* substr);
  58.     typedef BorNode<T> bor_type;
  59.     bor_type root;
  60.     vector<string> words;
  61.     bor_type* current_state;
  62.  
  63. public:
  64.     template<typename R>
  65.     void insert(const R &range)
  66.     {
  67.         insert(boost::begin(range), boost::end(range));
  68.     }
  69.  
  70.     template<typename ForwardIterator>
  71.     void insert(ForwardIterator begin, ForwardIterator end)
  72.     {
  73.         words.emplace_back(string());
  74.         words.back().reserve(std::distance(begin, end));
  75.  
  76.         bor_type *current_node = &root;
  77.         for(auto it = begin; it != end; ++it)
  78.         {
  79.             bor_type *child_node = current_node->getLink(*it);
  80.             if (!child_node)
  81.             {
  82.                 child_node = new bor_type(&root);
  83.                 current_node->links[*it] = child_node;
  84.             }
  85.             current_node = child_node;
  86.             words.back().push_back(*it);
  87.         }
  88.         current_node->out = true;
  89.         //current_node->out = int(words.size()) - 1;
  90.         //words.push_back(str);
  91.     }
  92.  
  93.     void init()
  94.     {
  95.         std::queue<bor_type *> q;
  96.         q.push(&root);
  97.         while (!q.empty())
  98.         {
  99.             bor_type *current_node = q.front();
  100.             q.pop();
  101.             for (auto iter = current_node->links.cbegin();
  102.                  iter != current_node->links.cend(); ++iter)
  103.             {
  104.                 const T symbol = iter->first;
  105.                 bor_type *child = iter->second;
  106.  
  107.                 // Defining .fail for the childnode
  108.                 bor_type *temp_node = current_node->fail;
  109.                 while (temp_node)
  110.                 {
  111.                     bor_type *fail_candidate = temp_node->getLink(symbol);
  112.                     if (fail_candidate)
  113.                     {
  114.                         child->fail = fail_candidate;
  115.                         break;
  116.                     }
  117.                     temp_node = temp_node->fail;
  118.                 }
  119.  
  120.                 // Defining .term for the childnode using .term of current node
  121.                 if (child->fail->isTerminal())
  122.                 {
  123.                     child->term = child->fail;
  124.                 }
  125.                 else
  126.                 {
  127.                     child->term = child->fail->term;
  128.                 }
  129.                 q.push(child);
  130.             }
  131.         }
  132.     }
  133.  
  134.     void step(const T& c)
  135.     {
  136.         while (current_state)
  137.         {
  138.             bor_type *candidate = current_state->getLink(c);
  139.             if (candidate)
  140.             {
  141.                 current_state = candidate;
  142.                 return;
  143.             }
  144.             current_state = current_state->fail;
  145.         }
  146.         current_state = &root;
  147.     }
  148.  
  149.     void printTermsForCurrentState(Callback callback) const
  150.     {
  151.         if (current_state->isTerminal()) {
  152.             //callback(words[current_state->out].c_str());
  153.         }
  154.         bor_type *temp_node = current_state->term;
  155.         while (temp_node) {
  156.             //callback(words[temp_node->out].c_str());
  157.             temp_node = temp_node->term;
  158.         }
  159.     }
  160.  
  161.     template <typename ForwardIterator>
  162.     void find(ForwardIterator begin, ForwardIterator end, Callback callback)
  163.     {
  164.         current_state = &root;
  165.         for(auto it = begin; it != end; ++it)
  166.         {
  167.             //cout << *str << ':' << endl;
  168.             step(*it);
  169.             //printTermsForCurrentState(callback);
  170.         }
  171.     }
  172. };
  173.  
  174. template<typename T, typename Compare = std::less<T>,
  175.          typename Alloc = std::allocator<std::pair<const T, BorNode<T> *>>,
  176.         typename ResultCont = std::vector<std::vector<T>>>
  177. using Aho_Corasik = AhoCorasick<T, std::map<T, BorNode<T> *, Compare, Alloc>, ResultCont>;
  178.  
  179. template<typename T, typename Hash = std::hash<T>, typename Pred = std::equal_to<T>,
  180.         typename Alloc = std::allocator<std::pair<const T, BorNode<T>*>>,
  181.         typename ResultCont = std::vector<std::vector<T>>>
  182. using Aho_Corasik_Hash = AhoCorasick<T, std::unordered_map<T, BorNode<T>*, Hash, Pred, Alloc>, ResultCont>;
  183.  
  184.  
  185. int main( )
  186. {
  187.     Aho_Corasik<char> ac;
  188.     Aho_Corasik_Hash<int> ach;
  189.  
  190.     return 0;
  191. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement