SlideShare una empresa de Scribd logo
1 de 112
Aho-Corasick string matching algorithm
an example implementation using C++11
       and behavior animation


                      Takatoshi Kondo
                    redboltz@gmail.com
     http://www.linkedin.com/profile/view?id=38098978
Aho-Corasick string matching algorithm

• When we want to match many fixed candidate
  strings, Aho-Corasick algorithm is efficient.
  – http://en.wikipedia.org/wiki/Aho%E2%80%93Cora
    sick_string_matching_algorithm
Source Code
class trie
template <typename T, template <class...> class KV = std::map, typename... Extra>
class trie {
public: // member functions
    template <typename TCol>
    void add(TCol const& keyCol) { ... }
    void create_revert_link() { ... }
    template <typename TCol>
    std::vector<TCol> find(TCol const& target) const { ... }
    template <typename TCol, typename Func>
    void find(TCol const& target, Func const& func) const { ... }
private: // types
    template <typename U>
    using rw = std::reference_wrapper<U>;

   struct node_t { ... };

   // Function object that returns collected outputs
   template <typename TCol>
   struct gather { ... };

private: // member variables
    node_t root_;
};




 https://gist.github.com/fcd8d77a1e0ef26ad360
Source Code
class trie
template <typename T, template <class...> class KV = std::map, typename... Extra>
class trie {
public: // member functions
    template <typename TCol>
    void add(TCol const& keyCol) { ... }
    void create_revert_link() { ... }
    template <typename TCol>
    std::vector<TCol> find(TCol const& target) const { ... }
    template <typename TCol, typename Func>
    void find(TCol const& target, Func const& func) const { ... }
private: // types
    template <typename U>
    using rw = std::reference_wrapper<U>;

   struct node_t { ... };

   // Function object that returns collected outputs
   template <typename TCol>
   struct gather { ... };

private: // member variables
    node_t root_;
};




 https://gist.github.com/fcd8d77a1e0ef26ad360
Source Code
inner class trie::node_t
  struct node_t {
      using children_col_t = KV<T, node_t, Extra...>;
      node_t():revert_link(*this), val() {}
      node_t(T const& val):revert_link(*this), val(val) {}
      node_t(node_t&&) = default;     // Movable
      node_t(node_t const&) = delete; // Non copyable

       std::vector<std::vector<T>> out;
       children_col_t children;
       rw<node_t> revert_link;
       T val;
  };


member function trie::add()
  template <typename TCol>
  void add(TCol const& keyCol) {
      static_assert(std::is_convertible<typename TCol::value_type, T>::value ,"");
      auto begin = boost::begin(keyCol);
      auto end = boost::end(keyCol);
      rw<node_t> current = root_;
      for (auto it = begin; it != end; ++it) {
          auto match = current.get().children.find(*it);
          if (match == current.get().children.end()) {
              auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it)));
              current = ret.first->second; // Added node
          }
          else {
              current = match->second;
          }
      }
      current.get().out.push_back(std::vector<T>(begin, end));
  }
Source Code
member function trie::create_revert_link()
  void create_revert_link() {
      std::deque<rw<node_t>> queue;
      for (auto& child : root_.children) {
          node_t& node = child.second;
          queue.push_back(std::ref(node));
          node.revert_link = std::ref(root_);
      }
      while (!queue.empty()) {
          rw<node_t> elem = queue.front();
          for (auto& subchild : elem.get().children) {
              T a = subchild.first;
              node_t& subnode = subchild.second;
              queue.push_back(std::ref(subnode));
              rw<node_t> v = elem.get().revert_link;
              while (true) {
                  auto const& it = v.get().children.find(a);
                  if (it == v.get().children.end()) {
                      if (&v.get() == &root_) {
                          subnode.revert_link = std::ref(root_);
                          break;
                      }
                      v = v.get().revert_link;
                  }
                  else {
                      subnode.revert_link = std::ref(it->second);
                      for (auto const& o : subnode.revert_link.get().out) {
                          subnode.out.push_back(o);
                      }
                      break;
                  }
              }
          }
          queue.pop_front();
      }
  }
Source Code
member function trie::find() - callback interface
  template <typename TCol, typename Func>
  void find(TCol const& target, Func const& func) const {
      static_assert(std::is_convertible<typename TCol::value_type, T>::value ,"");

      auto it = boost::begin(target);
      auto end = boost::end(target);
      rw<node_t const> current = root_;
                                                                  functor gather
      while (it != end) {                                             // Function object that returns collected outputs
          auto nit = current.get().children.find(*it);                template <typename TCol>
          if (nit == current.get().children.end()) {                  struct gather {
              if (&current.get() == &root_) {                             gather(std::vector<TCol>& col):col(col) {}
                  ++it;                                                   template <typename U>
              }                                                           void operator()(U const& u) const {
              else {                                                          col.push_back(TCol(boost::begin(u), boost::end(u)));
                  current = current.get().revert_link.get();              }
              }                                                       private:
          }                                                               std::vector<TCol>& col;
          else {                                                      };
              current = nit->second;
              ++it;
          }
          for (auto const& elem : current.get().out)
                                                                  member function trie::find() - return vector
              func(elem);                                             template <typename TCol>
      }                                                               std::vector<TCol> find(TCol const& target) const {
  }                                                                       std::vector<TCol> ret;
                                                                          find(target, gather<TCol>(ret));
                                                                          return ret;
                                                                      }
2 Phase Trie Construction
• Phase1
  – Construct Search Trie
• Phase2
  – Create reverse link
template <typename TCol>
Constructing search trie     void add(TCol const& keyCol) {
                               static_assert(std::is_convertible<typename TCol::value_type, T>::value ,"");
                     ABCDE     auto begin = boost::begin(keyCol);
                     ABC       auto end = boost::end(keyCol);
                               rw<node_t> current = root_;
                     CDE       for (auto it = begin; it != end; ++it) {
                                 auto match = current.get().children.find(*it);
  Search strings     BCD         if (match == current.get().children.end()) {
                     BBBC          auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it)));
                                   current = ret.first->second; // Added node
                                 }
                                 else {
                                   current = match->second;
                                 }
                               }
                               current.get().out.push_back(std::vector<T>(begin, end));
           Root              }



           R
template <typename TCol>
Constructing search trie         void add(TCol const& keyCol) {
                                   static_assert(std::is_convertible<typename TCol::value_type, T>::value ,"");
                     ABCDE         auto begin = boost::begin(keyCol);
                     ABC           auto end = boost::end(keyCol);
                                   rw<node_t> current = root_;
                     CDE           for (auto it = begin; it != end; ++it) {
                                     auto match = current.get().children.find(*it);
                     BCD             if (match == current.get().children.end()) {
                     BBBC              auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it)));
                                       current = ret.first->second; // Added node
                                     }
                                     else {
                                       current = match->second;
                                     }
                                   }
                                   current.get().out.push_back(std::vector<T>(begin, end));
                                 }



           R      A          B   C          D           E
template <typename TCol>
Constructing search trie         void add(TCol const& keyCol) {
                                   static_assert(std::is_convertible<typename TCol::value_type, T>::value ,"");
                     ABCDE         auto begin = boost::begin(keyCol);
                     ABC           auto end = boost::end(keyCol);
                                   rw<node_t> current = root_;
                     CDE           for (auto it = begin; it != end; ++it) {
                                     auto match = current.get().children.find(*it);
                     BCD             if (match == current.get().children.end()) {
                     BBBC              auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it)));
                                       current = ret.first->second; // Added node
                                     }
                                     else {
                                       current = match->second;
                                     }
                                   }
                                   current.get().out.push_back(std::vector<T>(begin, end));
                                 }



           R      A          B   C          D           E
                                                     ABCDE
template <typename TCol>
Constructing search trie         void add(TCol const& keyCol) {
                                   static_assert(std::is_convertible<typename TCol::value_type, T>::value ,"");
                     ABCDE         auto begin = boost::begin(keyCol);
                     ABC           auto end = boost::end(keyCol);
                                   rw<node_t> current = root_;
                     CDE           for (auto it = begin; it != end; ++it) {
                                     auto match = current.get().children.find(*it);
                     BCD             if (match == current.get().children.end()) {
                     BBBC              auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it)));
                                       current = ret.first->second; // Added node
                                     }
                                     else {
                                       current = match->second;
                                     }
                                   }
                                   current.get().out.push_back(std::vector<T>(begin, end));
                                 }



           R      A          B   C          D           E
                                                     ABCDE
template <typename TCol>
Constructing search trie         void add(TCol const& keyCol) {
                                   static_assert(std::is_convertible<typename TCol::value_type, T>::value ,"");
                     ABCDE         auto begin = boost::begin(keyCol);
                     ABC           auto end = boost::end(keyCol);
                                   rw<node_t> current = root_;
                     CDE           for (auto it = begin; it != end; ++it) {
                                     auto match = current.get().children.find(*it);
                     BCD             if (match == current.get().children.end()) {
                     BBBC              auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it)));
                                       current = ret.first->second; // Added node
                                     }
                                     else {
                                       current = match->second;
                                     }
                                   }
                                   current.get().out.push_back(std::vector<T>(begin, end));
                                 }



           R      A          B   C          D           E
                                 ABC                 ABCDE
template <typename TCol>
Constructing search trie         void add(TCol const& keyCol) {
                                   static_assert(std::is_convertible<typename TCol::value_type, T>::value ,"");
                     ABCDE         auto begin = boost::begin(keyCol);
                     ABC           auto end = boost::end(keyCol);
                                   rw<node_t> current = root_;
                     CDE           for (auto it = begin; it != end; ++it) {
                                     auto match = current.get().children.find(*it);
                     BCD             if (match == current.get().children.end()) {
                     BBBC              auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it)));
                                       current = ret.first->second; // Added node
                                     }
                                     else {
                                       current = match->second;
                                     }
                                   }
                                   current.get().out.push_back(std::vector<T>(begin, end));
                                 }



           R      A          B   C          D           E
                                 ABC                 ABCDE

                  C          D   E
                                 CDE
template <typename TCol>
Constructing search trie         void add(TCol const& keyCol) {
                                   static_assert(std::is_convertible<typename TCol::value_type, T>::value ,"");
                     ABCDE         auto begin = boost::begin(keyCol);
                     ABC           auto end = boost::end(keyCol);
                                   rw<node_t> current = root_;
                     CDE           for (auto it = begin; it != end; ++it) {
                                     auto match = current.get().children.find(*it);
                     BCD             if (match == current.get().children.end()) {
                     BBBC              auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it)));
                                       current = ret.first->second; // Added node
                                     }
                                     else {
                                       current = match->second;
                                     }
                                   }
                                   current.get().out.push_back(std::vector<T>(begin, end));
                                 }



           R      A          B   C          D           E
                                 ABC                 ABCDE

                  C          D   E
                                 CDE


                  B          C   D
                                 BCD
template <typename TCol>
Constructing search trie         void add(TCol const& keyCol) {
                                   static_assert(std::is_convertible<typename TCol::value_type, T>::value ,"");
                     ABCDE         auto begin = boost::begin(keyCol);
                     ABC           auto end = boost::end(keyCol);
                                   rw<node_t> current = root_;
                     CDE           for (auto it = begin; it != end; ++it) {
                                     auto match = current.get().children.find(*it);
                     BCD             if (match == current.get().children.end()) {
                     BBBC              auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it)));
                                       current = ret.first->second; // Added node
                                     }
                                     else {
                                       current = match->second;
                                     }
                                   }
                                   current.get().out.push_back(std::vector<T>(begin, end));
                                 }



           R      A          B   C          D           E
                                 ABC                 ABCDE

                  C          D   E
                                 CDE


                  B          C   D
                                 BCD
template <typename TCol>
Constructing search trie         void add(TCol const& keyCol) {
                                   static_assert(std::is_convertible<typename TCol::value_type, T>::value ,"");
                     ABCDE         auto begin = boost::begin(keyCol);
                     ABC           auto end = boost::end(keyCol);
                                   rw<node_t> current = root_;
                     CDE           for (auto it = begin; it != end; ++it) {
                                     auto match = current.get().children.find(*it);
                     BCD             if (match == current.get().children.end()) {
                     BBBC              auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it)));
                                       current = ret.first->second; // Added node
                                     }
                                     else {
                                       current = match->second;
                                     }
                                   }
                                   current.get().out.push_back(std::vector<T>(begin, end));
                                 }



           R      A          B   C          D           E
                                 ABC                 ABCDE

                  C          D   E
                                 CDE


                  B          C   D
                                 BCD

                             B   B          C
                                           BBBC
Create reverse link
                          ABCDE
                                               void create_revert_link() {
                          ABC                    std::deque<rw<node_t>> queue;
                                                 for (auto& child : root_.children) {
                          CDE                      node_t& node = child.second;
                          BCD                      queue.push_back(std::ref(node));
                                                   node.revert_link = std::ref(root_);
                          BBBC                   }
                                                 while (!queue.empty()) {
                                                   rw<node_t> elem = queue.front();
                                                   for (auto& subchild : elem.get().children) {
                                                     T a = subchild.first;
                                                     node_t& subnode = subchild.second;
                                                     queue.push_back(std::ref(subnode));
                                                     rw<node_t> v = elem.get().revert_link;
                                                     while (true) {
                                                       auto const& it = v.get().children.find(a);
                                                       if (it == v.get().children.end()) {
            R         A   B       C     D          E     if (&v.get() == &root_) {
                                                           subnode.revert_link = std::ref(root_);
                                  ABC            ABCDE break;
                                                         }
                                                         v = v.get().revert_link;
                      C   D       E                    }
                                  CDE                  else {
                                                         subnode.revert_link = std::ref(it->second);
                                                         for (auto const& o : subnode.revert_link.get().out) {
                                                           subnode.out.push_back(o);
                      B   C       D                      }
                                  BCD                    break;
                                                       }
                                                     }
                                                   }
                          B       B      C         queue.pop_front();
                                        BBBC     }
                                               }
Create reverse link                                     Breadth first seach
                          ABCDE
                                               void create_revert_link() {
                          ABC                    std::deque<rw<node_t>> queue;
                                                 for (auto& child : root_.children) {
                          CDE                      node_t& node = child.second;
                          BCD                      queue.push_back(std::ref(node));
                                                   node.revert_link = std::ref(root_);
                          BBBC                   }
                                                 while (!queue.empty()) {
                                                   rw<node_t> elem = queue.front();
                                                   for (auto& subchild : elem.get().children) {
                                                     T a = subchild.first;
                                                     node_t& subnode = subchild.second;
                                                     queue.push_back(std::ref(subnode));
                                                     rw<node_t> v = elem.get().revert_link;
                                                     while (true) {
                                                       auto const& it = v.get().children.find(a);
                                                       if (it == v.get().children.end()) {
            R         A   B       C     D          E     if (&v.get() == &root_) {
                                                           subnode.revert_link = std::ref(root_);
                                  ABC            ABCDE break;
                                                         }
                                                         v = v.get().revert_link;
                      C   D       E                    }
                                  CDE                  else {
                                                         subnode.revert_link = std::ref(it->second);
                                                         for (auto const& o : subnode.revert_link.get().out) {
                                                           subnode.out.push_back(o);
                      B   C       D                      }
                                  BCD                    break;
                                                       }
                                                     }
                                                   }
                          B       B      C         queue.pop_front();
                                        BBBC     }
                                               }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
                      A   C   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                                                         while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
                      A   C   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                                                         while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
                      A   C   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                                                         while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
           A              C   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                                                         while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
           A              C   B   B                      T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                              B                          while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
           A          C   B   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                              B                          while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
           A          C   B   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                              B                          while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
           A          C   B   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                              B                          while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
           A          C   B   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                              B                          while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
           A          C   B   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                              B                          while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
           A          C   B   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                              B                          while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
           A          C   B   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                              B                          while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
           A          C   B   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                              B                          while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
                      C   B   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                              B                          while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
                      C   B   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                                                         while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
            R         A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
          C               B   B                          T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                                                         while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
              R       A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                              ABCDE
                                                   void create_revert_link() {
                              ABC                    std::deque<rw<node_t>> queue;
                                                     for (auto& child : root_.children) {
                              CDE                      node_t& node = child.second;
                              BCD                      queue.push_back(std::ref(node));
                                                       node.revert_link = std::ref(root_);
                              BBBC                   }
                                                     while (!queue.empty()) {
                                                       rw<node_t> elem = queue.front();
                                                       for (auto& subchild : elem.get().children) {
          C               B   B D                        T a = subchild.first;
                                                         node_t& subnode = subchild.second;
                                                         queue.push_back(std::ref(subnode));
                                                         rw<node_t> v = elem.get().revert_link;
                              D                          while (true) {
                                                           auto const& it = v.get().children.find(a);
                                                           if (it == v.get().children.end()) {
              R       A       B       C     D          E     if (&v.get() == &root_) {
                                                               subnode.revert_link = std::ref(root_);
                                      ABC            ABCDE break;
                                                             }
                                                             v = v.get().revert_link;
                      C       D       E                    }
                                      CDE                  else {
                                                             subnode.revert_link = std::ref(it->second);
                                                             for (auto const& o : subnode.revert_link.get().out) {
                                                               subnode.out.push_back(o);
                      B       C       D                      }
                                      BCD                    break;
                                                           }
                                                         }
                                                       }
                              B       B      C         queue.pop_front();
                                            BBBC     }
                                                   }
Create reverse link
                            ABCDE
                                                 void create_revert_link() {
                            ABC                    std::deque<rw<node_t>> queue;
                                                   for (auto& child : root_.children) {
                            CDE                      node_t& node = child.second;
                            BCD                      queue.push_back(std::ref(node));
                                                     node.revert_link = std::ref(root_);
                            BBBC                   }
                                                   while (!queue.empty()) {
                                                     rw<node_t> elem = queue.front();
                                                     for (auto& subchild : elem.get().children) {
          C           B   B D                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            D                          while (true) {
                                                         auto const& it = v.get().children.find(a);
                                                         if (it == v.get().children.end()) {
              R       A     B       C     D          E     if (&v.get() == &root_) {
                                                             subnode.revert_link = std::ref(root_);
                                    ABC            ABCDE break;
                                                           }
                                                           v = v.get().revert_link;
                      C     D       E                    }
                                    CDE                  else {
                                                           subnode.revert_link = std::ref(it->second);
                                                           for (auto const& o : subnode.revert_link.get().out) {
                                                             subnode.out.push_back(o);
                      B     C       D                      }
                                    BCD                    break;
                                                         }
                                                       }
                                                     }
                            B       B      C         queue.pop_front();
                                          BBBC     }
                                                 }
Create reverse link
                            ABCDE
                                                 void create_revert_link() {
                            ABC                    std::deque<rw<node_t>> queue;
                                                   for (auto& child : root_.children) {
                            CDE                      node_t& node = child.second;
                            BCD                      queue.push_back(std::ref(node));
                                                     node.revert_link = std::ref(root_);
                            BBBC                   }
                                                   while (!queue.empty()) {
                                                     rw<node_t> elem = queue.front();
                                                     for (auto& subchild : elem.get().children) {
          C           B   B D                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            D                          while (true) {
                                                         auto const& it = v.get().children.find(a);
                                                         if (it == v.get().children.end()) {
              R       A     B       C     D          E     if (&v.get() == &root_) {
                                                             subnode.revert_link = std::ref(root_);
                                    ABC            ABCDE break;
                                                           }
                                                           v = v.get().revert_link;
                      C     D       E                    }
                                    CDE                  else {
                                                           subnode.revert_link = std::ref(it->second);
                                                           for (auto const& o : subnode.revert_link.get().out) {
                                                             subnode.out.push_back(o);
                      B     C       D                      }
                                    BCD                    break;
                                                         }
                                                       }
                                                     }
                            B       B      C         queue.pop_front();
                                          BBBC     }
                                                 }
Create reverse link
                            ABCDE
                                                 void create_revert_link() {
                            ABC                    std::deque<rw<node_t>> queue;
                                                   for (auto& child : root_.children) {
                            CDE                      node_t& node = child.second;
                            BCD                      queue.push_back(std::ref(node));
                                                     node.revert_link = std::ref(root_);
                            BBBC                   }
                                                   while (!queue.empty()) {
                                                     rw<node_t> elem = queue.front();
                                                     for (auto& subchild : elem.get().children) {
          C           B   B D                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            D                          while (true) {
                                                         auto const& it = v.get().children.find(a);
                                                         if (it == v.get().children.end()) {
              R       A     B       C     D          E     if (&v.get() == &root_) {
                                                             subnode.revert_link = std::ref(root_);
                                    ABC            ABCDE break;
                                                           }
                                                           v = v.get().revert_link;
                      C     D       E                    }
                                    CDE                  else {
                                                           subnode.revert_link = std::ref(it->second);
                                                           for (auto const& o : subnode.revert_link.get().out) {
                                                             subnode.out.push_back(o);
                      B     C       D                      }
                                    BCD                    break;
                                                         }
                                                       }
                                                     }
                            B       B      C         queue.pop_front();
                                          BBBC     }
                                                 }
Create reverse link
                            ABCDE
                                                 void create_revert_link() {
                            ABC                    std::deque<rw<node_t>> queue;
                                                   for (auto& child : root_.children) {
                            CDE                      node_t& node = child.second;
                            BCD                      queue.push_back(std::ref(node));
                                                     node.revert_link = std::ref(root_);
                            BBBC                   }
                                                   while (!queue.empty()) {
                                                     rw<node_t> elem = queue.front();
                                                     for (auto& subchild : elem.get().children) {
          C           B   B D                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            D                          while (true) {
                                                         auto const& it = v.get().children.find(a);
                                                         if (it == v.get().children.end()) {
              R       A     B       C     D          E     if (&v.get() == &root_) {
                                                             subnode.revert_link = std::ref(root_);
                                    ABC            ABCDE break;
                                                           }
                                                           v = v.get().revert_link;
                      C     D       E                    }
                                    CDE                  else {
                                                           subnode.revert_link = std::ref(it->second);
                                                           for (auto const& o : subnode.revert_link.get().out) {
                                                             subnode.out.push_back(o);
                      B     C       D                      }
                                    BCD                    break;
                                                         }
                                                       }
                                                     }
                            B       B      C         queue.pop_front();
                                          BBBC     }
                                                 }
Create reverse link
                            ABCDE
                                                    void create_revert_link() {
                            ABC                       std::deque<rw<node_t>> queue;
                                                      for (auto& child : root_.children) {
                            CDE                         node_t& node = child.second;
                            BCD                         queue.push_back(std::ref(node));
                                                        node.revert_link = std::ref(root_);
                            BBBC                      }
                                                      while (!queue.empty()) {
                                                        rw<node_t> elem = queue.front();
                                                        for (auto& subchild : elem.get().children) {
          C           B   B D                             T a = subchild.first;
                                                          node_t& subnode = subchild.second;
                                                          queue.push_back(std::ref(subnode));
                                                          rw<node_t> v = elem.get().revert_link;
                            D                             while (true) {
                                                            auto const& it = v.get().children.find(a);
                                                            if (it == v.get().children.end()) {
              R       A     B       C        D          E     if (&v.get() == &root_) {
                                                                subnode.revert_link = std::ref(root_);
                                    ABC               ABCDE break;
                                                              }
                                                              v = v.get().revert_link;
                      C     D       E                       }
                                    CDE                     else {
                                                              subnode.revert_link = std::ref(it->second);
                                                              for (auto const& o : subnode.revert_link.get().out) {
                                                                subnode.out.push_back(o);
                      B     C       D                         }
                                    BCD                       break;
                                                            }
                                                          }
                                                        }
                            B       B         C         queue.pop_front();
                                             BBBC     }
                                                    }
                          D does not exist
Create reverse link
                            ABCDE
                                                 void create_revert_link() {
                            ABC                    std::deque<rw<node_t>> queue;
                                                   for (auto& child : root_.children) {
                            CDE                      node_t& node = child.second;
                            BCD                      queue.push_back(std::ref(node));
                                                     node.revert_link = std::ref(root_);
                            BBBC                   }
                                                   while (!queue.empty()) {
                                                     rw<node_t> elem = queue.front();
                                                     for (auto& subchild : elem.get().children) {
                      B   B D                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            D                          while (true) {
                                                         auto const& it = v.get().children.find(a);
                                                         if (it == v.get().children.end()) {
            R         A     B       C     D          E     if (&v.get() == &root_) {
                                                             subnode.revert_link = std::ref(root_);
                                    ABC            ABCDE break;
                                                           }
                                                           v = v.get().revert_link;
                      C     D       E                    }
                                    CDE                  else {
                                                           subnode.revert_link = std::ref(it->second);
                                                           for (auto const& o : subnode.revert_link.get().out) {
                                                             subnode.out.push_back(o);
                      B     C       D                      }
                                    BCD                    break;
                                                         }
                                                       }
                                                     }
                            B       B      C         queue.pop_front();
                                          BBBC     }
                                                 }
Create reverse link
                            ABCDE
                                                 void create_revert_link() {
                            ABC                    std::deque<rw<node_t>> queue;
                                                   for (auto& child : root_.children) {
                            CDE                      node_t& node = child.second;
                            BCD                      queue.push_back(std::ref(node));
                                                     node.revert_link = std::ref(root_);
                            BBBC                   }
                                                   while (!queue.empty()) {
                                                     rw<node_t> elem = queue.front();
                                                     for (auto& subchild : elem.get().children) {
                      B   B D                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                                                       while (true) {
                                                         auto const& it = v.get().children.find(a);
                                                         if (it == v.get().children.end()) {
            R         A     B       C     D          E     if (&v.get() == &root_) {
                                                             subnode.revert_link = std::ref(root_);
                                    ABC            ABCDE break;
                                                           }
                                                           v = v.get().revert_link;
                      C     D       E                    }
                                    CDE                  else {
                                                           subnode.revert_link = std::ref(it->second);
                                                           for (auto const& o : subnode.revert_link.get().out) {
                                                             subnode.out.push_back(o);
                      B     C       D                      }
                                    BCD                    break;
                                                         }
                                                       }
                                                     }
                            B       B      C         queue.pop_front();
                                          BBBC     }
                                                 }
Create reverse link
                            ABCDE
                                                 void create_revert_link() {
                            ABC                    std::deque<rw<node_t>> queue;
                                                   for (auto& child : root_.children) {
                            CDE                      node_t& node = child.second;
                            BCD                      queue.push_back(std::ref(node));
                                                     node.revert_link = std::ref(root_);
                            BBBC                   }
                                                   while (!queue.empty()) {
                                                     rw<node_t> elem = queue.front();
                                                     for (auto& subchild : elem.get().children) {
          B               B D                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                                                       while (true) {
                                                         auto const& it = v.get().children.find(a);
                                                         if (it == v.get().children.end()) {
              R       A     B       C     D          E     if (&v.get() == &root_) {
                                                             subnode.revert_link = std::ref(root_);
                                    ABC            ABCDE break;
                                                           }
                                                           v = v.get().revert_link;
                      C     D       E                    }
                                    CDE                  else {
                                                           subnode.revert_link = std::ref(it->second);
                                                           for (auto const& o : subnode.revert_link.get().out) {
                                                             subnode.out.push_back(o);
                      B     C       D                      }
                                    BCD                    break;
                                                         }
                                                       }
                                                     }
                            B       B      C         queue.pop_front();
                                          BBBC     }
                                                 }
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm
Aho-Corasick string matching algorithm

Más contenido relacionado

La actualidad más candente

C# 6.0 - April 2014 preview
C# 6.0 - April 2014 previewC# 6.0 - April 2014 preview
C# 6.0 - April 2014 previewPaulo Morgado
 
Machine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting ConcernsMachine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting Concernssaintiss
 
Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”Platonov Sergey
 
C++totural file
C++totural fileC++totural file
C++totural filehalaisumit
 
C++ extension methods
C++ extension methodsC++ extension methods
C++ extension methodsphil_nash
 
Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]Dimitrios Platis
 
Advance features of C++
Advance features of C++Advance features of C++
Advance features of C++vidyamittal
 
Bartosz Milewski, “Re-discovering Monads in C++”
Bartosz Milewski, “Re-discovering Monads in C++”Bartosz Milewski, “Re-discovering Monads in C++”
Bartosz Milewski, “Re-discovering Monads in C++”Platonov Sergey
 
Functional "Life": parallel cellular automata and comonads
Functional "Life": parallel cellular automata and comonadsFunctional "Life": parallel cellular automata and comonads
Functional "Life": parallel cellular automata and comonadsAlexander Granin
 
Advance C++notes
Advance C++notesAdvance C++notes
Advance C++notesRajiv Gupta
 
6. Generics. Collections. Streams
6. Generics. Collections. Streams6. Generics. Collections. Streams
6. Generics. Collections. StreamsDEVTYPE
 
連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」matuura_core
 
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
"Немного о функциональном программирование в JavaScript" Алексей Коваленко"Немного о функциональном программирование в JavaScript" Алексей Коваленко
"Немного о функциональном программирование в JavaScript" Алексей КоваленкоFwdays
 

La actualidad más candente (20)

C# 6.0 - April 2014 preview
C# 6.0 - April 2014 previewC# 6.0 - April 2014 preview
C# 6.0 - April 2014 preview
 
Machine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting ConcernsMachine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting Concerns
 
Polymorphism
PolymorphismPolymorphism
Polymorphism
 
Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”
 
C++ tutorial
C++ tutorialC++ tutorial
C++ tutorial
 
C++totural file
C++totural fileC++totural file
C++totural file
 
C++ extension methods
C++ extension methodsC++ extension methods
C++ extension methods
 
Lambda expressions in C++
Lambda expressions in C++Lambda expressions in C++
Lambda expressions in C++
 
Voce Tem Orgulho Do Seu Codigo
Voce Tem Orgulho Do Seu CodigoVoce Tem Orgulho Do Seu Codigo
Voce Tem Orgulho Do Seu Codigo
 
Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]Writing SOLID C++ [gbgcpp meetup @ Zenseact]
Writing SOLID C++ [gbgcpp meetup @ Zenseact]
 
Advance features of C++
Advance features of C++Advance features of C++
Advance features of C++
 
C program
C programC program
C program
 
Bartosz Milewski, “Re-discovering Monads in C++”
Bartosz Milewski, “Re-discovering Monads in C++”Bartosz Milewski, “Re-discovering Monads in C++”
Bartosz Milewski, “Re-discovering Monads in C++”
 
Functional "Life": parallel cellular automata and comonads
Functional "Life": parallel cellular automata and comonadsFunctional "Life": parallel cellular automata and comonads
Functional "Life": parallel cellular automata and comonads
 
Advance C++notes
Advance C++notesAdvance C++notes
Advance C++notes
 
Container adapters
Container adaptersContainer adapters
Container adapters
 
6. Generics. Collections. Streams
6. Generics. Collections. Streams6. Generics. Collections. Streams
6. Generics. Collections. Streams
 
Academy PRO: ES2015
Academy PRO: ES2015Academy PRO: ES2015
Academy PRO: ES2015
 
連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」
 
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
"Немного о функциональном программирование в JavaScript" Алексей Коваленко"Немного о функциональном программирование в JavaScript" Алексей Коваленко
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
 

Destacado

String Matching Finite Automata & KMP Algorithm.
String Matching Finite Automata & KMP Algorithm.String Matching Finite Automata & KMP Algorithm.
String Matching Finite Automata & KMP Algorithm.Malek Sumaiya
 
String Matching with Finite Automata,Aho corasick,
String Matching with Finite Automata,Aho corasick,String Matching with Finite Automata,Aho corasick,
String Matching with Finite Automata,Aho corasick,8neutron8
 
Error detection and correction
Error detection and correctionError detection and correction
Error detection and correctionSiddique Ibrahim
 

Destacado (6)

日本語形態素解析
日本語形態素解析日本語形態素解析
日本語形態素解析
 
String Matching Finite Automata & KMP Algorithm.
String Matching Finite Automata & KMP Algorithm.String Matching Finite Automata & KMP Algorithm.
String Matching Finite Automata & KMP Algorithm.
 
String Matching with Finite Automata,Aho corasick,
String Matching with Finite Automata,Aho corasick,String Matching with Finite Automata,Aho corasick,
String Matching with Finite Automata,Aho corasick,
 
計算量とオーダー
計算量とオーダー計算量とオーダー
計算量とオーダー
 
計算量
計算量計算量
計算量
 
Error detection and correction
Error detection and correctionError detection and correction
Error detection and correction
 

Similar a Aho-Corasick string matching algorithm

I want help in the following C++ programming task. Please do coding .pdf
I want help in the following C++ programming task. Please do coding .pdfI want help in the following C++ programming task. Please do coding .pdf
I want help in the following C++ programming task. Please do coding .pdfbermanbeancolungak45
 
Need help with the TODO's (DONE IN C++) #pragma once #include -funct.pdf
Need help with the TODO's (DONE IN C++) #pragma once   #include -funct.pdfNeed help with the TODO's (DONE IN C++) #pragma once   #include -funct.pdf
Need help with the TODO's (DONE IN C++) #pragma once #include -funct.pdfactexerode
 
Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Platonov Sergey
 
C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴명신 김
 
Modern C++ Concurrency API
Modern C++ Concurrency APIModern C++ Concurrency API
Modern C++ Concurrency APISeok-joon Yun
 
C++17 introduction - Meetup @EtixLabs
C++17 introduction - Meetup @EtixLabsC++17 introduction - Meetup @EtixLabs
C++17 introduction - Meetup @EtixLabsStephane Gleizes
 
C++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operatorC++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operatorJussi Pohjolainen
 
Oops lab manual2
Oops lab manual2Oops lab manual2
Oops lab manual2Mouna Guru
 
C++ lectures all chapters in one slide.pptx
C++ lectures all chapters in one slide.pptxC++ lectures all chapters in one slide.pptx
C++ lectures all chapters in one slide.pptxssuser3cbb4c
 
Chainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたChainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたAkira Maruoka
 
C++17 not your father’s c++
C++17  not your father’s c++C++17  not your father’s c++
C++17 not your father’s c++Patrick Viafore
 
This is a c++ binary search program I worked so far but still cant g.pdf
This is a c++ binary search program I worked so far but still cant g.pdfThis is a c++ binary search program I worked so far but still cant g.pdf
This is a c++ binary search program I worked so far but still cant g.pdfkostikjaylonshaewe47
 
Templates in C++
Templates in C++Templates in C++
Templates in C++Tech_MX
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019corehard_by
 
Need help getting past an error in C++! I have all my code pasted down.docx
Need help getting past an error in C++! I have all my code pasted down.docxNeed help getting past an error in C++! I have all my code pasted down.docx
Need help getting past an error in C++! I have all my code pasted down.docxJason0x0Scottw
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Juan Pablo
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4Abed Bukhari
 

Similar a Aho-Corasick string matching algorithm (20)

C++11 - STL Additions
C++11 - STL AdditionsC++11 - STL Additions
C++11 - STL Additions
 
C++11
C++11C++11
C++11
 
I want help in the following C++ programming task. Please do coding .pdf
I want help in the following C++ programming task. Please do coding .pdfI want help in the following C++ programming task. Please do coding .pdf
I want help in the following C++ programming task. Please do coding .pdf
 
Need help with the TODO's (DONE IN C++) #pragma once #include -funct.pdf
Need help with the TODO's (DONE IN C++) #pragma once   #include -funct.pdfNeed help with the TODO's (DONE IN C++) #pragma once   #include -funct.pdf
Need help with the TODO's (DONE IN C++) #pragma once #include -funct.pdf
 
Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.
 
C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴
 
Modern C++ Concurrency API
Modern C++ Concurrency APIModern C++ Concurrency API
Modern C++ Concurrency API
 
C++17 introduction - Meetup @EtixLabs
C++17 introduction - Meetup @EtixLabsC++17 introduction - Meetup @EtixLabs
C++17 introduction - Meetup @EtixLabs
 
C++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operatorC++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operator
 
Oops lab manual2
Oops lab manual2Oops lab manual2
Oops lab manual2
 
C++ lectures all chapters in one slide.pptx
C++ lectures all chapters in one slide.pptxC++ lectures all chapters in one slide.pptx
C++ lectures all chapters in one slide.pptx
 
Chainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたChainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみた
 
C++17 not your father’s c++
C++17  not your father’s c++C++17  not your father’s c++
C++17 not your father’s c++
 
This is a c++ binary search program I worked so far but still cant g.pdf
This is a c++ binary search program I worked so far but still cant g.pdfThis is a c++ binary search program I worked so far but still cant g.pdf
This is a c++ binary search program I worked so far but still cant g.pdf
 
oop objects_classes
oop objects_classesoop objects_classes
oop objects_classes
 
Templates in C++
Templates in C++Templates in C++
Templates in C++
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
 
Need help getting past an error in C++! I have all my code pasted down.docx
Need help getting past an error in C++! I have all my code pasted down.docxNeed help getting past an error in C++! I have all my code pasted down.docx
Need help getting past an error in C++! I have all my code pasted down.docx
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4
 

Más de Takatoshi Kondo

CppCon2016 report and Boost.SML
CppCon2016 report and Boost.SMLCppCon2016 report and Boost.SML
CppCon2016 report and Boost.SMLTakatoshi Kondo
 
Pub/Sub model, msm, and asio
Pub/Sub model, msm, and asioPub/Sub model, msm, and asio
Pub/Sub model, msm, and asioTakatoshi Kondo
 
Effective Modern C++ study group Item39
Effective Modern C++ study group Item39Effective Modern C++ study group Item39
Effective Modern C++ study group Item39Takatoshi Kondo
 
MessagePack(msgpack): Compact and Fast Serialization Library
MessagePack(msgpack): Compact and Fast Serialization LibraryMessagePack(msgpack): Compact and Fast Serialization Library
MessagePack(msgpack): Compact and Fast Serialization LibraryTakatoshi Kondo
 
Boostsapporomsmpost 111106070819-phpapp02
Boostsapporomsmpost 111106070819-phpapp02Boostsapporomsmpost 111106070819-phpapp02
Boostsapporomsmpost 111106070819-phpapp02Takatoshi Kondo
 
Boostsapporomsmpre 111030054504-phpapp02
Boostsapporomsmpre 111030054504-phpapp02Boostsapporomsmpre 111030054504-phpapp02
Boostsapporomsmpre 111030054504-phpapp02Takatoshi Kondo
 
Unpack mechanism of the msgpack-c
Unpack mechanism of the msgpack-cUnpack mechanism of the msgpack-c
Unpack mechanism of the msgpack-cTakatoshi Kondo
 

Más de Takatoshi Kondo (11)

CppCon2016 report and Boost.SML
CppCon2016 report and Boost.SMLCppCon2016 report and Boost.SML
CppCon2016 report and Boost.SML
 
Pub/Sub model, msm, and asio
Pub/Sub model, msm, and asioPub/Sub model, msm, and asio
Pub/Sub model, msm, and asio
 
Effective Modern C++ study group Item39
Effective Modern C++ study group Item39Effective Modern C++ study group Item39
Effective Modern C++ study group Item39
 
Boost sg msgpack
Boost sg msgpackBoost sg msgpack
Boost sg msgpack
 
MessagePack(msgpack): Compact and Fast Serialization Library
MessagePack(msgpack): Compact and Fast Serialization LibraryMessagePack(msgpack): Compact and Fast Serialization Library
MessagePack(msgpack): Compact and Fast Serialization Library
 
Emcpp0506
Emcpp0506Emcpp0506
Emcpp0506
 
Boostsapporomsmpost 111106070819-phpapp02
Boostsapporomsmpost 111106070819-phpapp02Boostsapporomsmpost 111106070819-phpapp02
Boostsapporomsmpost 111106070819-phpapp02
 
Boostsapporomsmpre 111030054504-phpapp02
Boostsapporomsmpre 111030054504-phpapp02Boostsapporomsmpre 111030054504-phpapp02
Boostsapporomsmpre 111030054504-phpapp02
 
Unpack mechanism of the msgpack-c
Unpack mechanism of the msgpack-cUnpack mechanism of the msgpack-c
Unpack mechanism of the msgpack-c
 
N3495 inplace realloc
N3495 inplace reallocN3495 inplace realloc
N3495 inplace realloc
 
N3701 concept lite
N3701 concept liteN3701 concept lite
N3701 concept lite
 

Aho-Corasick string matching algorithm

  • 1. Aho-Corasick string matching algorithm an example implementation using C++11 and behavior animation Takatoshi Kondo redboltz@gmail.com http://www.linkedin.com/profile/view?id=38098978
  • 2. Aho-Corasick string matching algorithm • When we want to match many fixed candidate strings, Aho-Corasick algorithm is efficient. – http://en.wikipedia.org/wiki/Aho%E2%80%93Cora sick_string_matching_algorithm
  • 3. Source Code class trie template <typename T, template <class...> class KV = std::map, typename... Extra> class trie { public: // member functions template <typename TCol> void add(TCol const& keyCol) { ... } void create_revert_link() { ... } template <typename TCol> std::vector<TCol> find(TCol const& target) const { ... } template <typename TCol, typename Func> void find(TCol const& target, Func const& func) const { ... } private: // types template <typename U> using rw = std::reference_wrapper<U>; struct node_t { ... }; // Function object that returns collected outputs template <typename TCol> struct gather { ... }; private: // member variables node_t root_; }; https://gist.github.com/fcd8d77a1e0ef26ad360
  • 4. Source Code class trie template <typename T, template <class...> class KV = std::map, typename... Extra> class trie { public: // member functions template <typename TCol> void add(TCol const& keyCol) { ... } void create_revert_link() { ... } template <typename TCol> std::vector<TCol> find(TCol const& target) const { ... } template <typename TCol, typename Func> void find(TCol const& target, Func const& func) const { ... } private: // types template <typename U> using rw = std::reference_wrapper<U>; struct node_t { ... }; // Function object that returns collected outputs template <typename TCol> struct gather { ... }; private: // member variables node_t root_; }; https://gist.github.com/fcd8d77a1e0ef26ad360
  • 5. Source Code inner class trie::node_t struct node_t { using children_col_t = KV<T, node_t, Extra...>; node_t():revert_link(*this), val() {} node_t(T const& val):revert_link(*this), val(val) {} node_t(node_t&&) = default; // Movable node_t(node_t const&) = delete; // Non copyable std::vector<std::vector<T>> out; children_col_t children; rw<node_t> revert_link; T val; }; member function trie::add() template <typename TCol> void add(TCol const& keyCol) { static_assert(std::is_convertible<typename TCol::value_type, T>::value ,""); auto begin = boost::begin(keyCol); auto end = boost::end(keyCol); rw<node_t> current = root_; for (auto it = begin; it != end; ++it) { auto match = current.get().children.find(*it); if (match == current.get().children.end()) { auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it))); current = ret.first->second; // Added node } else { current = match->second; } } current.get().out.push_back(std::vector<T>(begin, end)); }
  • 6. Source Code member function trie::create_revert_link() void create_revert_link() { std::deque<rw<node_t>> queue; for (auto& child : root_.children) { node_t& node = child.second; queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); break; } v = v.get().revert_link; } else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); } break; } } } queue.pop_front(); } }
  • 7. Source Code member function trie::find() - callback interface template <typename TCol, typename Func> void find(TCol const& target, Func const& func) const { static_assert(std::is_convertible<typename TCol::value_type, T>::value ,""); auto it = boost::begin(target); auto end = boost::end(target); rw<node_t const> current = root_; functor gather while (it != end) { // Function object that returns collected outputs auto nit = current.get().children.find(*it); template <typename TCol> if (nit == current.get().children.end()) { struct gather { if (&current.get() == &root_) { gather(std::vector<TCol>& col):col(col) {} ++it; template <typename U> } void operator()(U const& u) const { else { col.push_back(TCol(boost::begin(u), boost::end(u))); current = current.get().revert_link.get(); } } private: } std::vector<TCol>& col; else { }; current = nit->second; ++it; } for (auto const& elem : current.get().out) member function trie::find() - return vector func(elem); template <typename TCol> } std::vector<TCol> find(TCol const& target) const { } std::vector<TCol> ret; find(target, gather<TCol>(ret)); return ret; }
  • 8. 2 Phase Trie Construction • Phase1 – Construct Search Trie • Phase2 – Create reverse link
  • 9. template <typename TCol> Constructing search trie void add(TCol const& keyCol) { static_assert(std::is_convertible<typename TCol::value_type, T>::value ,""); ABCDE auto begin = boost::begin(keyCol); ABC auto end = boost::end(keyCol); rw<node_t> current = root_; CDE for (auto it = begin; it != end; ++it) { auto match = current.get().children.find(*it); Search strings BCD if (match == current.get().children.end()) { BBBC auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it))); current = ret.first->second; // Added node } else { current = match->second; } } current.get().out.push_back(std::vector<T>(begin, end)); Root } R
  • 10. template <typename TCol> Constructing search trie void add(TCol const& keyCol) { static_assert(std::is_convertible<typename TCol::value_type, T>::value ,""); ABCDE auto begin = boost::begin(keyCol); ABC auto end = boost::end(keyCol); rw<node_t> current = root_; CDE for (auto it = begin; it != end; ++it) { auto match = current.get().children.find(*it); BCD if (match == current.get().children.end()) { BBBC auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it))); current = ret.first->second; // Added node } else { current = match->second; } } current.get().out.push_back(std::vector<T>(begin, end)); } R A B C D E
  • 11. template <typename TCol> Constructing search trie void add(TCol const& keyCol) { static_assert(std::is_convertible<typename TCol::value_type, T>::value ,""); ABCDE auto begin = boost::begin(keyCol); ABC auto end = boost::end(keyCol); rw<node_t> current = root_; CDE for (auto it = begin; it != end; ++it) { auto match = current.get().children.find(*it); BCD if (match == current.get().children.end()) { BBBC auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it))); current = ret.first->second; // Added node } else { current = match->second; } } current.get().out.push_back(std::vector<T>(begin, end)); } R A B C D E ABCDE
  • 12. template <typename TCol> Constructing search trie void add(TCol const& keyCol) { static_assert(std::is_convertible<typename TCol::value_type, T>::value ,""); ABCDE auto begin = boost::begin(keyCol); ABC auto end = boost::end(keyCol); rw<node_t> current = root_; CDE for (auto it = begin; it != end; ++it) { auto match = current.get().children.find(*it); BCD if (match == current.get().children.end()) { BBBC auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it))); current = ret.first->second; // Added node } else { current = match->second; } } current.get().out.push_back(std::vector<T>(begin, end)); } R A B C D E ABCDE
  • 13. template <typename TCol> Constructing search trie void add(TCol const& keyCol) { static_assert(std::is_convertible<typename TCol::value_type, T>::value ,""); ABCDE auto begin = boost::begin(keyCol); ABC auto end = boost::end(keyCol); rw<node_t> current = root_; CDE for (auto it = begin; it != end; ++it) { auto match = current.get().children.find(*it); BCD if (match == current.get().children.end()) { BBBC auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it))); current = ret.first->second; // Added node } else { current = match->second; } } current.get().out.push_back(std::vector<T>(begin, end)); } R A B C D E ABC ABCDE
  • 14. template <typename TCol> Constructing search trie void add(TCol const& keyCol) { static_assert(std::is_convertible<typename TCol::value_type, T>::value ,""); ABCDE auto begin = boost::begin(keyCol); ABC auto end = boost::end(keyCol); rw<node_t> current = root_; CDE for (auto it = begin; it != end; ++it) { auto match = current.get().children.find(*it); BCD if (match == current.get().children.end()) { BBBC auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it))); current = ret.first->second; // Added node } else { current = match->second; } } current.get().out.push_back(std::vector<T>(begin, end)); } R A B C D E ABC ABCDE C D E CDE
  • 15. template <typename TCol> Constructing search trie void add(TCol const& keyCol) { static_assert(std::is_convertible<typename TCol::value_type, T>::value ,""); ABCDE auto begin = boost::begin(keyCol); ABC auto end = boost::end(keyCol); rw<node_t> current = root_; CDE for (auto it = begin; it != end; ++it) { auto match = current.get().children.find(*it); BCD if (match == current.get().children.end()) { BBBC auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it))); current = ret.first->second; // Added node } else { current = match->second; } } current.get().out.push_back(std::vector<T>(begin, end)); } R A B C D E ABC ABCDE C D E CDE B C D BCD
  • 16. template <typename TCol> Constructing search trie void add(TCol const& keyCol) { static_assert(std::is_convertible<typename TCol::value_type, T>::value ,""); ABCDE auto begin = boost::begin(keyCol); ABC auto end = boost::end(keyCol); rw<node_t> current = root_; CDE for (auto it = begin; it != end; ++it) { auto match = current.get().children.find(*it); BCD if (match == current.get().children.end()) { BBBC auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it))); current = ret.first->second; // Added node } else { current = match->second; } } current.get().out.push_back(std::vector<T>(begin, end)); } R A B C D E ABC ABCDE C D E CDE B C D BCD
  • 17. template <typename TCol> Constructing search trie void add(TCol const& keyCol) { static_assert(std::is_convertible<typename TCol::value_type, T>::value ,""); ABCDE auto begin = boost::begin(keyCol); ABC auto end = boost::end(keyCol); rw<node_t> current = root_; CDE for (auto it = begin; it != end; ++it) { auto match = current.get().children.find(*it); BCD if (match == current.get().children.end()) { BBBC auto ret = current.get().children.insert(std::make_pair(*it, node_t(*it))); current = ret.first->second; // Added node } else { current = match->second; } } current.get().out.push_back(std::vector<T>(begin, end)); } R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 18. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 19. Create reverse link Breadth first seach ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 20. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { A C B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 21. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { A C B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 22. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { A C B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 23. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { A C B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 24. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { A C B B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; B while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 25. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { A C B B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; B while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 26. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { A C B B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; B while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 27. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { A C B B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; B while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 28. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { A C B B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; B while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 29. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { A C B B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; B while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 30. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { A C B B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; B while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 31. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { A C B B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; B while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 32. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { A C B B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; B while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 33. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { C B B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; B while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 34. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { C B B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 35. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { C B B T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 36. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { C B B D T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; D while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 37. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { C B B D T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; D while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 38. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { C B B D T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; D while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 39. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { C B B D T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; D while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 40. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { C B B D T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; D while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 41. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { C B B D T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; D while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } } D does not exist
  • 42. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { B B D T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; D while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 43. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { B B D T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }
  • 44. Create reverse link ABCDE void create_revert_link() { ABC std::deque<rw<node_t>> queue; for (auto& child : root_.children) { CDE node_t& node = child.second; BCD queue.push_back(std::ref(node)); node.revert_link = std::ref(root_); BBBC } while (!queue.empty()) { rw<node_t> elem = queue.front(); for (auto& subchild : elem.get().children) { B B D T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; while (true) { auto const& it = v.get().children.find(a); if (it == v.get().children.end()) { R A B C D E if (&v.get() == &root_) { subnode.revert_link = std::ref(root_); ABC ABCDE break; } v = v.get().revert_link; C D E } CDE else { subnode.revert_link = std::ref(it->second); for (auto const& o : subnode.revert_link.get().out) { subnode.out.push_back(o); B C D } BCD break; } } } B B C queue.pop_front(); BBBC } }