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     }
                                                 }
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 C                        T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            C                          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   C                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            C                          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   C                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            C                          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   C                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            C                          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   C                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            C                          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   C                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            C                          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   C                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            C                          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   C                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            C                          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   C                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            C                          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   C                          T a = subchild.first;
                                                       node_t& subnode = subchild.second;
                                                       queue.push_back(std::ref(subnode));
                                                       rw<node_t> v = elem.get().revert_link;
                            C                          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   C                          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   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;
                            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) {
                      B D   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
                              ABC
                              CDE
                              BCD
                              BBBC

          B               D   C   B


                              C

              R       A       B       C     D       E
                                      ABC          ABCDE

                      C       D       E
                                      CDE


                      B       C       D
                                      BCD

                              B       B      C
                                            BBBC
Create reverse link
                              ABCDE
                              ABC
                              CDE
                              BCD
                              BBBC

          B               D   C   B   C


                              C

              R       A       B       C     D       E
                                      ABC          ABCDE

                      C       D       E
                                      CDE


                      B       C       D
                                      BCD

                              B       B      C
                                            BBBC
Create reverse link
                              ABCDE
                              ABC
                              CDE
                              BCD
                              BBBC

          B               D   C   B   C


                              C

              R       A       B       C     D       E
                                      ABC          ABCDE

                      C       D       E
                                      CDE


                      B       C       D
                                      BCD

                              B       B      C
                                            BBBC
Create reverse link
                              ABCDE
                              ABC
                              CDE
                              BCD
                              BBBC

          B               D   C   B   C


                              C

              R       A       B       C     D       E
                                      ABC          ABCDE

                      C       D       E
                                      CDE


                      B       C       D
                                      BCD

                              B       B      C
                                            BBBC
Create reverse link
                              ABCDE
                              ABC
                              CDE
                              BCD
                              BBBC

          B               D   C   B   C


                              C

              R       A       B       C     D       E
                                      ABC          ABCDE

                      C       D       E
                                      CDE


                      B       C       D
                                      BCD

                              B       B      C
                                            BBBC
Create reverse link
                              ABCDE
                              ABC
                              CDE
                              BCD
                              BBBC

          B               D   C   B   C


                              C

              R       A       B       C     D       E
                                      ABC          ABCDE

                      C       D       E
                                      CDE


                      B       C       D
                                      BCD

                              B       B      C
                                            BBBC
Create reverse link
                              ABCDE
                              ABC
                              CDE
                              BCD
                              BBBC

          B               D   C   B   C


                              C

              R       A       B       C     D       E
                                      ABC          ABCDE

                      C       D       E
                                      CDE


                      B       C       D
                                      BCD

                              B       B      C
                                            BBBC
Create reverse link
                              ABCDE
                              ABC
                              CDE
                              BCD
                              BBBC

          B               D   C   B   C


                              C

              R       A       B       C     D       E
                                      ABC          ABCDE

                      C       D       E
                                      CDE


                      B       C       D
                                      BCD

                              B       B      C
                                            BBBC
Create reverse link
                              ABCDE
                              ABC
                              CDE
                              BCD
                              BBBC

          B               D   C   B   C


                              C

              R       A       B       C     D       E
                                      ABC          ABCDE

                      C       D       E
                                      CDE


                      B       C       D
                                      BCD

                              B       B      C
                                            BBBC
Create reverse link
                              ABCDE
                              ABC
                              CDE
                              BCD
                              BBBC

                          D   C   B   C


                              C

            R         A       B       C     D       E
                                      ABC          ABCDE

                      C       D       E
                                      CDE


                      B       C       D
                                      BCD

                              B       B      C
                                            BBBC
Create reverse link
                              ABCDE
                              ABC
                              CDE
                              BCD
                              BBBC

                          D   C   B   C




            R         A       B       C     D       E
                                      ABC          ABCDE

                      C       D       E
                                      CDE


                      B       C       D
                                      BCD

                              B       B      C
                                            BBBC
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC

                          C   B   C     E


                          E

            R         A   B       C         D       E
                                  ABC              ABCDE

                      C   D       E
                                  CDE


                      B   C       D
                                  BCD

                          B       B          C
                                            BBBC
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC

                              B   C     E   D


                          D

            R         A   B       C         D       E
                                  ABC              ABCDE

                      C   D       E
                                  CDE


                      B   C       D
                                  BCD

                          B       B          C
                                            BBBC
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC

                                  C     E   D B


                          B

            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) {
                                           E    D 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        BCD      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     }
                                                       }

                          Copy the out string
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC

                                              B D




            R         A   B       C     D           E
                                  ABC   BCD     ABCDE

                      C   D       E
                                  CDE


                      B   C       D
                                  BCD

                          B       B      C
                                        BBBC
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC

                                               D       C


                          C

            R         A   B       C     D          E
                                  ABC   BCD    ABCDE

                      C   D       E
                                  CDE


                      B   C       D
                                  BCD

                          B       B      C
                                        BBBC
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC

                                               D       C


                          C

            R         A   B       C     D          E
                                  ABC   BCD    ABCDE

                      C   D       E
                                  CDE


                      B   C       D
                                  BCD

                          B       B      C
                                        BBBC
Create reverse link
                            ABCDE
                            ABC
                            CDE
                            BCD
                            BBBC

                                                    D       C


                            C

            R         A     B       C        D          E
                                    ABC      BCD    ABCDE

                      C     D       E
                                    CDE


                      B     C       D
                                    BCD

                            B       B         C
                                             BBBC

                          C does not exist
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC

                                               D       C


                          C

            R         A   B       C     D          E
                                  ABC   BCD    ABCDE

                      C   D       E
                                  CDE


                      B   C       D
                                  BCD

                          B       B      C
                                        BBBC
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC

                                               D       C


                          C

            R         A   B       C     D          E
                                  ABC   BCD    ABCDE

                      C   D       E
                                  CDE


                      B   C       D
                                  BCD

                          B       B      C
                                        BBBC
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC

                                               D       C


                          C

            R         A   B       C     D          E
                                  ABC   BCD    ABCDE

                      C   D       E
                                  CDE


                      B   C       D
                                  BCD

                          B       B      C
                                        BBBC
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC

                                               D       C


                          C

            R         A   B       C     D          E
                                  ABC   BCD    ABCDE

                      C   D       E
                                  CDE


                      B   C       D
                                  BCD

                          B       B      C
                                        BBBC
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC

                                                          E


                          E

            R         A   B       C     D          E
                                  ABC   BCD      ABCDE
                                                  CDE
                      C   D       E
                                  CDE


                      B   C       D          Copy the out string
                                  BCD

                          B       B      C
                                        BBBC
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC




            R         A   B       C     D       E
                                  ABC   BCD    ABCDE
                                                CDE
                      C   D       E
                                  CDE


                      B   C       D
                                  BCD

                          B       B      C
                                        BBBC
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC




            R         A   B       C     D       E
                                  ABC   BCD    ABCDE
                                                CDE
                      C   D       E
                                  CDE


                      B   C       D
                                  BCD

                          B       B      C
                                        BBBC
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC




            R         A   B       C     D       E
                                  ABC   BCD    ABCDE
                                                CDE
                      C   D       E
                                  CDE


                      B   C       D
                                  BCD

                          B       B      C
                                        BBBC
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC




            R         A   B       C     D       E
                                  ABC   BCD    ABCDE
                                                CDE
                      C   D       E
                                  CDE


                      B   C       D
                                  BCD

                          B       B      C
                                        BBBC
Create reverse link
                          ABCDE
                          ABC
                          CDE
                          BCD
                          BBBC




            R         A   B       C     D       E
                                  ABC   BCD    ABCDE
                                                CDE
                      C   D       E
                                  CDE


                      B   C       D
                                  BCD

                          B       B      C
                                        BBBC
Search Strings
• Search strings using constructed trie structure
  with reverse links.
Search string
                                  ABCDE
                                  ABC
      Search strings              CDE
                                  BCD
                                  BBBC
                       Target string
                                                            template <typename TCol, typename Func>
            ZABBBBCDEZ                                      void find(TCol const& target, Func const& func) const {
                                                              auto it = boost::begin(target);
                                                              auto end = boost::end(target);
                                                              rw<node_t const> current = root_;
                                                              while (it != end) {
                                                                auto nit = current.get().children.find(*it);
             R           A         B      C     D        E      if (nit == current.get().children.end()) {
                                          ABC   BCD    ABCDE      if (&current.get() == &root_) {
                                                                    ++it;
                                                        CDE       }
                                                                  else {
                         C         D      E                         current = current.get().revert_link.get();
                                          CDE                     }
                                                                }
                                                                else {
                         B         C      D                       current = nit->second;
                                                                  ++it;
                                          BCD                   }
                                                                for (auto const& elem : current.get().out)
                                                                  func(elem);
                                   B      B      C            }
                                                            }
                                                BBBC
Search string
                            ABCDE
                            ABC
                            CDE
                            BCD
                            BBBC


                                                            template <typename TCol, typename Func>
            ZABBBBCDEZ                                      void find(TCol const& target, Func const& func) const {
                                                              auto it = boost::begin(target);
                Forward link 'Z' is not detected              auto end = boost::end(target);
                                                              rw<node_t const> current = root_;
                                                              while (it != end) {
                                                                auto nit = current.get().children.find(*it);
            R      A         B         C           D     E      if (nit == current.get().children.end()) {
                                      ABC      BCD     ABCDE      if (&current.get() == &root_) {
                                                                    ++it;
                                                        CDE       }
                                                                  else {
                   C         D         E                            current = current.get().revert_link.get();
                                      CDE                         }
                                                                }
                                                                else {
                   B         C        D                           current = nit->second;
                                                                  ++it;
                                      BCD                       }
                                                                for (auto const& elem : current.get().out)
                                                                  func(elem);
                             B         B           C          }
                                                            }
                                               BBBC
Search string
                              ABCDE
                              ABC
                              CDE
                              BCD
                              BBBC


                                                              template <typename TCol, typename Func>
            ZABBBBCDEZ                                        void find(TCol const& target, Func const& func) const {
                                                                auto it = boost::begin(target);
                  Forward link 'Z' is not detected              auto end = boost::end(target);
                                                                rw<node_t const> current = root_;
                                                                while (it != end) {
                                                                  auto nit = current.get().children.find(*it);
             R          A      B         C           D     E      if (nit == current.get().children.end()) {
                                        ABC      BCD     ABCDE      if (&current.get() == &root_) {
                                                                      ++it;
                                                          CDE       }
                                                                    else {
                        C      D         E                            current = current.get().revert_link.get();
                                        CDE                         }
 Current node is root                                             }
                                                                  else {
                        B      C        D                           current = nit->second;
                                                                    ++it;
                                        BCD                       }
                                                                  for (auto const& elem : current.get().out)
                                                                    func(elem);
                               B         B           C          }
                                                              }
                                                 BBBC
Search string
                            ABCDE
                            ABC
                            CDE
                            BCD
                            BBBC


                                                            template <typename TCol, typename Func>
            ZABBBBCDEZ                                      void find(TCol const& target, Func const& func) const {
                                                              auto it = boost::begin(target);
                The forward link 'A' is detected              auto end = boost::end(target);
                                                              rw<node_t const> current = root_;
                                                              while (it != end) {
                                                                auto nit = current.get().children.find(*it);
            R      A         B         C           D     E      if (nit == current.get().children.end()) {
                                      ABC      BCD     ABCDE      if (&current.get() == &root_) {
                                                                    ++it;
                                                        CDE       }
                                                                  else {
                   C         D         E                            current = current.get().revert_link.get();
                                      CDE                         }
                                                                }
                                                                else {
                   B         C        D                           current = nit->second;
                                                                  ++it;
                                     BCD                        }
                                                                for (auto const& elem : current.get().out)
                                                                  func(elem);
                             B         B           C          }
                                                            }
                                               BBBC
Search string
                            ABCDE
                            ABC
                            CDE
                            BCD
                            BBBC


                                                            template <typename TCol, typename Func>
            ZABBBBCDEZ                                      void find(TCol const& target, Func const& func) const {
                                                              auto it = boost::begin(target);
                The forward link 'B' is detected              auto end = boost::end(target);
                                                              rw<node_t const> current = root_;
                                                              while (it != end) {
                                                                auto nit = current.get().children.find(*it);
            R      A         B         C           D     E      if (nit == current.get().children.end()) {
                                      ABC      BCD     ABCDE      if (&current.get() == &root_) {
                                                                    ++it;
                                                        CDE       }
                                                                  else {
                   C         D         E                            current = current.get().revert_link.get();
                                      CDE                         }
                                                                }
                                                                else {
                   B         C        D                           current = nit->second;
                                                                  ++it;
                                      BCD                       }
                                                                for (auto const& elem : current.get().out)
                                                                  func(elem);
                             B         B           C          }
                                                            }
                                               BBBC
Search string
                               ABCDE
                               ABC
                               CDE
                               BCD
                               BBBC


                                                                  template <typename TCol, typename Func>
            ZABBBBCDEZ                                            void find(TCol const& target, Func const& func) const {
                                                                    auto it = boost::begin(target);
                The forward link 'B' is   not detected              auto end = boost::end(target);
                                                                    rw<node_t const> current = root_;
                                                                    while (it != end) {
                                                                      auto nit = current.get().children.find(*it);
            R        A          B           C          D          E   if (nit == current.get().children.end()) {
                                           ABC      BCD     ABCDE       if (&current.get() == &root_) {
                                                                          ++it;
                                                             CDE        }
                                                                        else {
                      C        D            E                             current = current.get().revert_link.get();
                                           CDE                          }
                                                                      }
                                                        Trying reverse link
                                                                      else {
                      B         C           D                           current = nit->second;
                                                                        ++it;
                                           BCD                        }
                                                                      for (auto const& elem : current.get().out)
                                                                        func(elem);
                                B           B          C            }
                                                                  }
                                                     BBBC
Search string
                               ABCDE
                               ABC
                               CDE
                               BCD
                               BBBC


                                                                  template <typename TCol, typename Func>
            ZABBBBCDEZ                                            void find(TCol const& target, Func const& func) const {
                                                                    auto it = boost::begin(target);
                The forward link 'B' is   not detected              auto end = boost::end(target);
                                                                    rw<node_t const> current = root_;
                                                                    while (it != end) {
                                                                      auto nit = current.get().children.find(*it);
            R        A          B           C          D          E   if (nit == current.get().children.end()) {
                                           ABC      BCD     ABCDE       if (&current.get() == &root_) {
                                                                          ++it;
                                                             CDE        }
                                                                        else {
                      C        D            E                             current = current.get().revert_link.get();
                                           CDE                          }
                                                                      }
                                                        Trying reverse link
                                                                      else {
                      B         C           D                           current = nit->second;
                                                                        ++it;
                                           BCD                        }
                                                                      for (auto const& elem : current.get().out)
                                                                        func(elem);
                                B           B          C            }
                                                                  }
                                                     BBBC

                  Try forward link again
Search string
                             ABCDE
                             ABC
                             CDE
                             BCD
                             BBBC


                                                               template <typename TCol, typename Func>
            ZABBBBCDEZ                                         void find(TCol const& target, Func const& func) const {
                                                                 auto it = boost::begin(target);
                                                                 auto end = boost::end(target);
                                                                 rw<node_t const> current = root_;
                                                                 while (it != end) {
                                                                   auto nit = current.get().children.find(*it);
            R       A         B        C           D        E      if (nit == current.get().children.end()) {
                                      ABC          BCD    ABCDE      if (&current.get() == &root_) {
                                                                       ++it;
                                                           CDE       }
                                                                     else {
                    C         D        E                               current = current.get().revert_link.get();
                                      CDE                            }
                                                                   }
                                                                   else {
                    B         C        D                             current = nit->second;
                                                                     ++it;
                                      BCD                          }
                                                                   for (auto const& elem : current.get().out)
                                                                     func(elem);
                              B        B            C            }
                                                               }
                                                   BBBC

                The forward link 'B' is detected
Search string
                               ABCDE
                               ABC
                               CDE
                               BCD
                               BBBC


                                                              template <typename TCol, typename Func>
            ZABBBBCDEZ                                        void find(TCol const& target, Func const& func) const {
                                                                auto it = boost::begin(target);
                                                                auto end = boost::end(target);
                                                                rw<node_t const> current = root_;
                                                                while (it != end) {
                                                                  auto nit = current.get().children.find(*it);
            R         A         B        C         D       E      if (nit == current.get().children.end()) {
                                        ABC       BCD    ABCDE      if (&current.get() == &root_) {
                                                                      ++it;
                                                          CDE       }
                                                                    else {
                      C         D        E                            current = current.get().revert_link.get();
                                        CDE                         }
                                                                  }
                                                                  else {
                      B         C        D                          current = nit->second;
                                                                    ++it;
                                        BCD                       }
                                                                  for (auto const& elem : current.get().out)
                                                                    func(elem);
                                B        B         C            }
                                                              }
                                                  BBBC

                The forward link 'B' is not detected
Search string
                             ABCDE
                             ABC
                             CDE
                             BCD
                             BBBC


                                                        template <typename TCol, typename Func>
            ZABBBBCDEZ                                  void find(TCol const& target, Func const& func) const {
                                                          auto it = boost::begin(target);
                                                          auto end = boost::end(target);
                                                          rw<node_t const> current = root_;
                                                          while (it != end) {
                                                            auto nit = current.get().children.find(*it);
            R     A          B         C    D        E      if (nit == current.get().children.end()) {
                                      ABC   BCD    ABCDE      if (&current.get() == &root_) {
                                                                ++it;
                                                    CDE       }
                                                              else {
                  C          D         E                        current = current.get().revert_link.get();
                                      CDE                     }
                                                            }
                                                            else {
                  B          C         D                      current = nit->second;
                                                              ++it;
                                      BCD                   }
                                                            for (auto const& elem : current.get().out)
                                                              func(elem);
                             B         B     C            }
                                                        }
                                            BBBC

                      Trying reverse link
Search string
                           ABCDE
                           ABC
                           CDE
                           BCD
                           BBBC


                                                         template <typename TCol, typename Func>
            ZABBBBCDEZ                                   void find(TCol const& target, Func const& func) const {
                                                           auto it = boost::begin(target);
                                                           auto end = boost::end(target);
                                                           rw<node_t const> current = root_;
                                                           while (it != end) {
                                                             auto nit = current.get().children.find(*it);
            R     A         B        C       D        E      if (nit == current.get().children.end()) {
                                    ABC      BCD    ABCDE      if (&current.get() == &root_) {
                                                                 ++it;
                                                     CDE       }
                                                               else {
                   C        D            E                       current = current.get().revert_link.get();
                                     CDE                       }
                                                             }
                                                             else {
                  B         C        D                         current = nit->second;
                                                               ++it;
                                    BCD                      }
                                                             for (auto const& elem : current.get().out)
                                                               func(elem);
                            B        B        C            }
                                                         }
                                             BBBC

                Try forward link again
Search string
                           ABCDE
                           ABC
                           CDE
                           BCD
                           BBBC


                                                         template <typename TCol, typename Func>
            ZABBBBCDEZ                                   void find(TCol const& target, Func const& func) const {
                                                           auto it = boost::begin(target);
                                                           auto end = boost::end(target);
                                                           rw<node_t const> current = root_;
                                                           while (it != end) {
                                                             auto nit = current.get().children.find(*it);
            R     A         B        C       D        E      if (nit == current.get().children.end()) {
                                    ABC      BCD    ABCDE      if (&current.get() == &root_) {
                                                                 ++it;
                                                     CDE       }
                                                               else {
                   C        D            E                       current = current.get().revert_link.get();
                                     CDE                       }
                                                             }
                                                             else {
                  B         C        D                         current = nit->second;
                                                               ++it;
                                    BCD                      }
                                                             for (auto const& elem : current.get().out)
                                                               func(elem);
                            B        B        C            }
                                                         }
                                             BBBC

                Try forward link again       The forward link 'B' is detected
Search string
                         ABCDE
                         ABC
                         CDE
                         BCD
                         BBBC


                                                           template <typename TCol, typename Func>
            ZABBBBCDEZ                                     void find(TCol const& target, Func const& func) const {
                                                             auto it = boost::begin(target);
                                                             auto end = boost::end(target);
                                                             rw<node_t const> current = root_;
                                                             while (it != end) {
                                                               auto nit = current.get().children.find(*it);
            R     A      B          C         D         E      if (nit == current.get().children.end()) {
                                   ABC       BCD      ABCDE      if (&current.get() == &root_) {
                                                                   ++it;
                                                       CDE       }
                                                                 else {
                  C      D          E                              current = current.get().revert_link.get();
                                   CDE                           }
                                                               }
                                                               else {
                  B      C          D                            current = nit->second;
                                                                 ++it;
                                   BCD                         }
                                                               for (auto const& elem : current.get().out)
                                                                 func(elem);
                         B          B         C              }
                                                           }
                                             BBBC

                             The forward link 'C' is detected
Search string
                         ABCDE
                         ABC
                         CDE
                         BCD
                         BBBC
                 BBBC

                                                           template <typename TCol, typename Func>
            ZABBBBCDEZ                                     void find(TCol const& target, Func const& func) const {
                                                             auto it = boost::begin(target);
                                                             auto end = boost::end(target);
                                                             rw<node_t const> current = root_;
                                                             while (it != end) {
                                                               auto nit = current.get().children.find(*it);
            R     A      B          C         D         E      if (nit == current.get().children.end()) {
                                   ABC       BCD      ABCDE      if (&current.get() == &root_) {
                                                                   ++it;
                                                       CDE       }
                                                                 else {
                  C      D          E                              current = current.get().revert_link.get();
                                   CDE                           }
                                                               }
                                                               else {
                  B      C          D                            current = nit->second;
                                                                 ++it;
                                   BCD                         }
                                                               for (auto const& elem : current.get().out)
                                                                 func(elem);
                         B          B         C              }
                                                           }
                                             BBBC
                                                                    The link has an output
                             The forward link 'C' is detected
Search string
                         ABCDE
                         ABC
                         CDE
                         BCD
                         BBBC
                 BBBC

                                                           template <typename TCol, typename Func>
            ZABBBBCDEZ                                     void find(TCol const& target, Func const& func) const {
                                                             auto it = boost::begin(target);
                                                             auto end = boost::end(target);
                                                             rw<node_t const> current = root_;
                                                             while (it != end) {
                                                               auto nit = current.get().children.find(*it);
            R     A       B         C          D        E      if (nit == current.get().children.end()) {
                                   ABC         BCD    ABCDE      if (&current.get() == &root_) {
                                                                   ++it;
                                                       CDE       }
                                                                 else {
                  C       D         E                              current = current.get().revert_link.get();
                                   CDE                           }
                                                               }
                                                               else {
                  B       C        D                             current = nit->second;
                                                                 ++it;
                                  BCD                          }
                                                               for (auto const& elem : current.get().out)
                                                                 func(elem);
                          B         B           C            }
                                                           }
                                               BBBC
                                                         The forward link 'D' is not detected
                         Trying reverse link
Search string
                                ABCDE
                                ABC
                                CDE
                                BCD
                      BCD       BBBC
                     BBBC

                                                                   template <typename TCol, typename Func>
             ZABBBBCDEZ                                            void find(TCol const& target, Func const& func) const {
                                                                     auto it = boost::begin(target);
                                                                     auto end = boost::end(target);
                                                                     rw<node_t const> current = root_;
                                                                     while (it != end) {
                                                                       auto nit = current.get().children.find(*it);
             R         A        B         C          D          E      if (nit == current.get().children.end()) {
                                         ABC         BCD     ABCDE       if (&current.get() == &root_) {
                                                                           ++it;
                                                              CDE        }
                                                                         else {
                       C        D         E                                current = current.get().revert_link.get();
                                         CDE                             }
                                                The link    has an output
                                                                       }
                                                                       else {
                       B        C        D                               current = nit->second;
                                                                         ++it;
                                        BCD                            }
                                                                       for (auto const& elem : current.get().out)
                                                                         func(elem);
                                B         B           C              }
                                                                   }
 The forward link 'D' is detected                    BBBC
                                                                 The forward link 'D' is not detected
                               Trying reverse link
Search string
                         ABCDE
                         ABC
                         CDE
                         BCD
                  BCD    BBBC
                 BBBC

                                                    template <typename TCol, typename Func>
            ZABBBBCDEZ                              void find(TCol const& target, Func const& func) const {
                                                      auto it = boost::begin(target);
                                                      auto end = boost::end(target);
                                                      rw<node_t const> current = root_;
                                                      while (it != end) {
                                                        auto nit = current.get().children.find(*it);
            R     A      B       C     D         E      if (nit == current.get().children.end()) {
                                 ABC   BCD     ABCDE      if (&current.get() == &root_) {
                                                            ++it;
                                                CDE       }
                                                          else {
                  C      D       E                          current = current.get().revert_link.get();
                                 CDE                      }
                                              The forward link 'E' is not detected
                                                        }
                                                        else {
                  B      C       D                        current = nit->second;
                                                          ++it;
                                 BCD             Trying}reverse link
                                                        for (auto const& elem : current.get().out)
                                                          func(elem);
                         B       B      C             }
                                                    }
                                       BBBC
Search string
                                  ABCDE
                                  ABC
                                  CDE
                                  BCD
                       BCD        BBBC
                      BBBC

                                                                template <typename TCol, typename Func>
            ZABBBBCDEZ                                          void find(TCol const& target, Func const& func) const {
                                                                  auto it = boost::begin(target);
                                                                  auto end = boost::end(target);
                The forward link 'E' is detected                  rw<node_t const> current = root_;
                                                                  while (it != end) {
                                                                    auto nit = current.get().children.find(*it);
            R           A         B         C      D         E      if (nit == current.get().children.end()) {
                                           ABC     BCD     ABCDE      if (&current.get() == &root_) {
                                                                        ++it;
                                                            CDE       }
                                                                      else {
                        C         D         E                           current = current.get().revert_link.get();
                                           CDE                        }
                                                          The forward link 'E' is not detected
                                                                    }
                                                                    else {
                        B         C         D                         current = nit->second;
                                                                      ++it;
                                           BCD               Trying}reverse link
                                                                    for (auto const& elem : current.get().out)
                                                                      func(elem);
                                  B         B       C             }
                                                                }
                                                   BBBC
Search string
                                  ABCDE
                                  ABC
                                  CDE
                         CDE
                                  BCD
                       BCD        BBBC
                      BBBC

                                                                template <typename TCol, typename Func>
            ZABBBBCDEZ                                          void find(TCol const& target, Func const& func) const {
                                                                  auto it = boost::begin(target);
                                                                  auto end = boost::end(target);
                The forward link 'E' is detected                  rw<node_t const> current = root_;
                                                                  while (it != end) {
                                                                    auto nit = current.get().children.find(*it);
            R           A         B         C      D         E      if (nit == current.get().children.end()) {
                                           ABC     BCD     ABCDE      if (&current.get() == &root_) {
                                                                        ++it;
                                                            CDE       }
                        C         D         E                     The link has an output
                                                                      else {
                                                                        current = current.get().revert_link.get();
                                           CDE                        }
                                                          The forward link 'E' is not detected
                                                                    }
                                                                    else {
                        B         C         D                         current = nit->second;
                                                                      ++it;
                                           BCD               Trying}reverse link
                                                                    for (auto const& elem : current.get().out)
                                                                      func(elem);
                                  B         B       C             }
                                                                }
                                                   BBBC
Search string
                          ABCDE
                          ABC
                          CDE
                    CDE
                          BCD
                  BCD     BBBC
                 BBBC


            ZABBBBCDEZ


            R     A       B       C     D         E
                                  ABC   BCD     ABCDE
                                                 CDE
                  C       D       E
                                  CDE
                                               The forward link 'Z' is not detected
                  B       C       D
                                  BCD

                          B       B      C
                                        BBBC
Search string
                             ABCDE
                             ABC
                             CDE
                     CDE
                             BCD
                   BCD       BBBC
                  BBBC

                                                         template <typename TCol, typename Func>
            ZABBBBCDEZ                                   void find(TCol const& target, Func const& func) const {
                                                           auto it = boost::begin(target);
                                                           auto end = boost::end(target);
                                                           rw<node_t const> current = root_;
                                                           while (it != end) {
                                                             auto nit = current.get().children.find(*it);
            R       A         B       C     D         E      if (nit == current.get().children.end()) {
                                      ABC   BCD     ABCDE      if (&current.get() == &root_) {
                                                                 ++it;
                                                     CDE       }
                                                               else {
                    C         D       E                          current = current.get().revert_link.get();
                                      CDE                      }
                                                   The forward link 'Z' is not detected
                                                             }
                                                             else {
                    B         C       D                        current = nit->second;
                                                               ++it;
                                      BCD                    }
                                                             for (auto const& elem : current.get().out)
                                                               func(elem);
                              B       B      C             }
                                                         }
                                            BBBC

                Trying reverse link
Search string
                              ABCDE
                              ABC
                              CDE
                      CDE
                              BCD
                    BCD       BBBC
                   BBBC

                                                              template <typename TCol, typename Func>
            ZABBBBCDEZ                                        void find(TCol const& target, Func const& func) const {
                                                                auto it = boost::begin(target);
                                                                auto end = boost::end(target);
          The forward link 'Z' is not detected                  rw<node_t const> current = root_;
                                                                while (it != end) {
                                                                  auto nit = current.get().children.find(*it);
            R        A         B         C       D         E      if (nit == current.get().children.end()) {
                                        ABC      BCD     ABCDE      if (&current.get() == &root_) {
                                                                      ++it;
                                                          CDE       }
                                                                    else {
                     C         D         E                            current = current.get().revert_link.get();
                                        CDE                         }
                                                        The forward link 'Z' is not detected
                                                                  }
                                                                  else {
                     B         C        D                           current = nit->second;
                                                                    ++it;
                                        BCD                       }
                                                                  for (auto const& elem : current.get().out)
                                                                    func(elem);
                               B         B        C             }
                                                              }
                                                 BBBC

                 Trying reverse link
Search string
                               ABCDE
                               ABC
                               CDE
                       CDE
                               BCD
                     BCD       BBBC
                    BBBC

                                                               template <typename TCol, typename Func>
            ZABBBBCDEZ                                         void find(TCol const& target, Func const& func) const {
                                                                 auto it = boost::begin(target);
                                                                 auto end = boost::end(target);
           The forward link 'Z' is not detected                  rw<node_t const> current = root_;
                                                                 while (it != end) {
                                                                   auto nit = current.get().children.find(*it);
             R        A         B         C       D         E      if (nit == current.get().children.end()) {
                                         ABC      BCD     ABCDE      if (&current.get() == &root_) {
                                                                       ++it;
                                                           CDE       }
                                                                     else {
                      C         D         E                            current = current.get().revert_link.get();
                                         CDE                         }
    Current node is root                                 The forward link 'Z' is not detected
                                                                   }
                                                                   else {
                      B         C        D                           current = nit->second;
                                                                     ++it;
                                         BCD                       }
                                                                   for (auto const& elem : current.get().out)
                                                                     func(elem);
                                B         B        C             }
                                                               }
                                                  BBBC

                  Trying reverse link
Search string
                          ABCDE
                          ABC
                          CDE
                    CDE
                          BCD
                  BCD     BBBC
                 BBBC

                                                    template <typename TCol, typename Func>
            ZABBBBCDEZ                              void find(TCol const& target, Func const& func) const {
                                                      auto it = boost::begin(target);
                                                      auto end = boost::end(target);
                                                      rw<node_t const> current = root_;
                                                      while (it != end) {
                                                        auto nit = current.get().children.find(*it);
            R     A       B       C     D        E      if (nit == current.get().children.end()) {
                                  ABC   BCD    ABCDE      if (&current.get() == &root_) {
                                                            ++it;
                                                CDE       }
                                                          else {
                  C       D       E                         current = current.get().revert_link.get();
                                  CDE                     }
                                                        }
                                                        else {
                  B       C       D                       current = nit->second;
                                                          ++it;
                                  BCD                   }
                                                        for (auto const& elem : current.get().out)
                                                          func(elem);
                          B       B      C            }
                                                    }
                                        BBBC
Search string
                          ABCDE
                          ABC
                          CDE
                    CDE
                          BCD
                  BCD     BBBC
                 BBBC
                                      These three strings are detected

            ZABBBBCDEZ


            R     A       B       C         D         E
                                  ABC      BCD     ABCDE
                                                    CDE
                  C       D       E
                                  CDE


                  B       C       D
                                  BCD

                          B       B         C
                                           BBBC

More Related Content

PPTX
Top down parsing
ODP
Garbage collection
PPTX
Lexical analysis - Compiler Design
PDF
Daa notes 1
PPTX
Graph in data structure
PPTX
Hashing and Hashtable, application of hashing, advantages of hashing, disadva...
PPTX
Predictive parser
PPT
Top down parsing
Top down parsing
Garbage collection
Lexical analysis - Compiler Design
Daa notes 1
Graph in data structure
Hashing and Hashtable, application of hashing, advantages of hashing, disadva...
Predictive parser
Top down parsing

What's hot (20)

PPTX
PHP FUNCTIONS
PPTX
Data Structures : hashing (1)
PDF
PPTX
PPTX
Compiler Design - Ambiguous grammar, LMD & RMD, Infix & Postfix, Implementati...
PDF
Python : Regular expressions
PPTX
Hash table in data structure and algorithm
PDF
Aho corasick-lecture
PPT
MYSQL - PHP Database Connectivity
PPTX
Multi processor scheduling
PPT
Hash tables
PPS
Java Exception handling
PPTX
Working with arrays in php
PDF
Bottom up parser
PPSX
Modules and packages in python
PDF
Introduction to OpenMP
PPT
Chapter 5 Presentation
PPTX
Exception handling
PPTX
COMPILER DESIGN
PDF
LR(1) CLR(1) Parser with Example
PHP FUNCTIONS
Data Structures : hashing (1)
Compiler Design - Ambiguous grammar, LMD & RMD, Infix & Postfix, Implementati...
Python : Regular expressions
Hash table in data structure and algorithm
Aho corasick-lecture
MYSQL - PHP Database Connectivity
Multi processor scheduling
Hash tables
Java Exception handling
Working with arrays in php
Bottom up parser
Modules and packages in python
Introduction to OpenMP
Chapter 5 Presentation
Exception handling
COMPILER DESIGN
LR(1) CLR(1) Parser with Example
Ad

Viewers also liked (6)

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

Similar to Aho-Corasick string matching algorithm (20)

PDF
C++ extension methods
PPTX
C++11 - STL Additions
PPTX
PDF
I want help in the following C++ programming task. Please do coding .pdf
PDF
Need help with the TODO's (DONE IN C++) #pragma once #include -funct.pdf
PPT
Евгений Крутько, Многопоточные вычисления, современный подход.
PPTX
C#을 이용한 task 병렬화와 비동기 패턴
PDF
Modern C++ Concurrency API
PDF
The STL
DOC
Ds 2 cycle
PDF
C++17 introduction - Meetup @EtixLabs
PPT
C++: Constructor, Copy Constructor and Assignment operator
DOC
Oops lab manual2
PPTX
C++ lectures all chapters in one slide.pptx
PDF
Chainer-Compiler 動かしてみた
PDF
C++17 not your father’s c++
PDF
This is a c++ binary search program I worked so far but still cant g.pdf
PPT
oop objects_classes
PPTX
Templates in C++
PDF
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
C++ extension methods
C++11 - STL Additions
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
Евгений Крутько, Многопоточные вычисления, современный подход.
C#을 이용한 task 병렬화와 비동기 패턴
Modern C++ Concurrency API
The STL
Ds 2 cycle
C++17 introduction - Meetup @EtixLabs
C++: Constructor, Copy Constructor and Assignment operator
Oops lab manual2
C++ lectures all chapters in one slide.pptx
Chainer-Compiler 動かしてみた
C++17 not your father’s c++
This is a c++ binary search program I worked so far but still cant g.pdf
oop objects_classes
Templates in C++
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019

More from Takatoshi Kondo (11)

PPTX
CppCon2016 report and Boost.SML
PPTX
Pub/Sub model, msm, and asio
PPTX
Effective Modern C++ study group Item39
PDF
Boost sg msgpack
PDF
MessagePack(msgpack): Compact and Fast Serialization Library
PPTX
Emcpp0506
PDF
Boostsapporomsmpost 111106070819-phpapp02
PDF
Boostsapporomsmpre 111030054504-phpapp02
PPTX
Unpack mechanism of the msgpack-c
PPTX
N3495 inplace realloc
PPTX
N3701 concept lite
CppCon2016 report and Boost.SML
Pub/Sub model, msm, and asio
Effective Modern C++ study group Item39
Boost sg msgpack
MessagePack(msgpack): Compact and Fast Serialization Library
Emcpp0506
Boostsapporomsmpost 111106070819-phpapp02
Boostsapporomsmpre 111030054504-phpapp02
Unpack mechanism of the msgpack-c
N3495 inplace realloc
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 [email protected] 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 } }
  • 45. 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 C T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; C 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 } }
  • 46. 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 C T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; C 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 } }
  • 47. 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 C T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; C 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 } }
  • 48. 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 C T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; C 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 } }
  • 49. 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 C T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; C 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 } }
  • 50. 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 C T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; C 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 } }
  • 51. 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 C T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; C 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 } }
  • 52. 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 C T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; C 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 } }
  • 53. 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 C T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; C 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 } }
  • 54. 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 C T a = subchild.first; node_t& subnode = subchild.second; queue.push_back(std::ref(subnode)); rw<node_t> v = elem.get().revert_link; C 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 } }
  • 55. 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 C 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 } }
  • 56. 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 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; 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 } }
  • 57. 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 D 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 } }
  • 58. Create reverse link ABCDE ABC CDE BCD BBBC B D C B C R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 59. Create reverse link ABCDE ABC CDE BCD BBBC B D C B C C R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 60. Create reverse link ABCDE ABC CDE BCD BBBC B D C B C C R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 61. Create reverse link ABCDE ABC CDE BCD BBBC B D C B C C R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 62. Create reverse link ABCDE ABC CDE BCD BBBC B D C B C C R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 63. Create reverse link ABCDE ABC CDE BCD BBBC B D C B C C R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 64. Create reverse link ABCDE ABC CDE BCD BBBC B D C B C C R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 65. Create reverse link ABCDE ABC CDE BCD BBBC B D C B C C R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 66. Create reverse link ABCDE ABC CDE BCD BBBC B D C B C C R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 67. Create reverse link ABCDE ABC CDE BCD BBBC D C B C C R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 68. Create reverse link ABCDE ABC CDE BCD BBBC D C B C R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 69. Create reverse link ABCDE ABC CDE BCD BBBC C B C E E R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 70. Create reverse link ABCDE ABC CDE BCD BBBC B C E D D R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 71. Create reverse link ABCDE ABC CDE BCD BBBC C E D B B R A B C D E ABC ABCDE C D E CDE B C D BCD B B C BBBC
  • 72. 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) { E D 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 BCD 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 } } Copy the out string
  • 73. Create reverse link ABCDE ABC CDE BCD BBBC B D R A B C D E ABC BCD ABCDE C D E CDE B C D BCD B B C BBBC
  • 74. Create reverse link ABCDE ABC CDE BCD BBBC D C C R A B C D E ABC BCD ABCDE C D E CDE B C D BCD B B C BBBC
  • 75. Create reverse link ABCDE ABC CDE BCD BBBC D C C R A B C D E ABC BCD ABCDE C D E CDE B C D BCD B B C BBBC
  • 76. Create reverse link ABCDE ABC CDE BCD BBBC D C C R A B C D E ABC BCD ABCDE C D E CDE B C D BCD B B C BBBC C does not exist
  • 77. Create reverse link ABCDE ABC CDE BCD BBBC D C C R A B C D E ABC BCD ABCDE C D E CDE B C D BCD B B C BBBC
  • 78. Create reverse link ABCDE ABC CDE BCD BBBC D C C R A B C D E ABC BCD ABCDE C D E CDE B C D BCD B B C BBBC
  • 79. Create reverse link ABCDE ABC CDE BCD BBBC D C C R A B C D E ABC BCD ABCDE C D E CDE B C D BCD B B C BBBC
  • 80. Create reverse link ABCDE ABC CDE BCD BBBC D C C R A B C D E ABC BCD ABCDE C D E CDE B C D BCD B B C BBBC
  • 81. Create reverse link ABCDE ABC CDE BCD BBBC E E R A B C D E ABC BCD ABCDE CDE C D E CDE B C D Copy the out string BCD B B C BBBC
  • 82. Create reverse link ABCDE ABC CDE BCD BBBC R A B C D E ABC BCD ABCDE CDE C D E CDE B C D BCD B B C BBBC
  • 83. Create reverse link ABCDE ABC CDE BCD BBBC R A B C D E ABC BCD ABCDE CDE C D E CDE B C D BCD B B C BBBC
  • 84. Create reverse link ABCDE ABC CDE BCD BBBC R A B C D E ABC BCD ABCDE CDE C D E CDE B C D BCD B B C BBBC
  • 85. Create reverse link ABCDE ABC CDE BCD BBBC R A B C D E ABC BCD ABCDE CDE C D E CDE B C D BCD B B C BBBC
  • 86. Create reverse link ABCDE ABC CDE BCD BBBC R A B C D E ABC BCD ABCDE CDE C D E CDE B C D BCD B B C BBBC
  • 87. Search Strings • Search strings using constructed trie structure with reverse links.
  • 88. Search string ABCDE ABC Search strings CDE BCD BBBC Target string template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC
  • 89. Search string ABCDE ABC CDE BCD BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); Forward link 'Z' is not detected auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC
  • 90. Search string ABCDE ABC CDE BCD BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); Forward link 'Z' is not detected auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } Current node is root } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC
  • 91. Search string ABCDE ABC CDE BCD BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); The forward link 'A' is detected auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC
  • 92. Search string ABCDE ABC CDE BCD BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); The forward link 'B' is detected auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC
  • 93. Search string ABCDE ABC CDE BCD BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); The forward link 'B' is not detected auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } Trying reverse link else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC
  • 94. Search string ABCDE ABC CDE BCD BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); The forward link 'B' is not detected auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } Trying reverse link else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC Try forward link again
  • 95. Search string ABCDE ABC CDE BCD BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC The forward link 'B' is detected
  • 96. Search string ABCDE ABC CDE BCD BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC The forward link 'B' is not detected
  • 97. Search string ABCDE ABC CDE BCD BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC Trying reverse link
  • 98. Search string ABCDE ABC CDE BCD BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC Try forward link again
  • 99. Search string ABCDE ABC CDE BCD BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC Try forward link again The forward link 'B' is detected
  • 100. Search string ABCDE ABC CDE BCD BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC The forward link 'C' is detected
  • 101. Search string ABCDE ABC CDE BCD BBBC BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC The link has an output The forward link 'C' is detected
  • 102. Search string ABCDE ABC CDE BCD BBBC BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC The forward link 'D' is not detected Trying reverse link
  • 103. Search string ABCDE ABC CDE BCD BCD BBBC BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } The link has an output } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } The forward link 'D' is detected BBBC The forward link 'D' is not detected Trying reverse link
  • 104. Search string ABCDE ABC CDE BCD BCD BBBC BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } The forward link 'E' is not detected } else { B C D current = nit->second; ++it; BCD Trying}reverse link for (auto const& elem : current.get().out) func(elem); B B C } } BBBC
  • 105. Search string ABCDE ABC CDE BCD BCD BBBC BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); The forward link 'E' is detected rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } The forward link 'E' is not detected } else { B C D current = nit->second; ++it; BCD Trying}reverse link for (auto const& elem : current.get().out) func(elem); B B C } } BBBC
  • 106. Search string ABCDE ABC CDE CDE BCD BCD BBBC BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); The forward link 'E' is detected rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } C D E The link has an output else { current = current.get().revert_link.get(); CDE } The forward link 'E' is not detected } else { B C D current = nit->second; ++it; BCD Trying}reverse link for (auto const& elem : current.get().out) func(elem); B B C } } BBBC
  • 107. Search string ABCDE ABC CDE CDE BCD BCD BBBC BBBC ZABBBBCDEZ R A B C D E ABC BCD ABCDE CDE C D E CDE The forward link 'Z' is not detected B C D BCD B B C BBBC
  • 108. Search string ABCDE ABC CDE CDE BCD BCD BBBC BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } The forward link 'Z' is not detected } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC Trying reverse link
  • 109. Search string ABCDE ABC CDE CDE BCD BCD BBBC BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); The forward link 'Z' is not detected rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } The forward link 'Z' is not detected } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC Trying reverse link
  • 110. Search string ABCDE ABC CDE CDE BCD BCD BBBC BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); The forward link 'Z' is not detected rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } Current node is root The forward link 'Z' is not detected } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC Trying reverse link
  • 111. Search string ABCDE ABC CDE CDE BCD BCD BBBC BBBC template <typename TCol, typename Func> ZABBBBCDEZ void find(TCol const& target, Func const& func) const { auto it = boost::begin(target); auto end = boost::end(target); rw<node_t const> current = root_; while (it != end) { auto nit = current.get().children.find(*it); R A B C D E if (nit == current.get().children.end()) { ABC BCD ABCDE if (&current.get() == &root_) { ++it; CDE } else { C D E current = current.get().revert_link.get(); CDE } } else { B C D current = nit->second; ++it; BCD } for (auto const& elem : current.get().out) func(elem); B B C } } BBBC
  • 112. Search string ABCDE ABC CDE CDE BCD BCD BBBC BBBC These three strings are detected ZABBBBCDEZ R A B C D E ABC BCD ABCDE CDE C D E CDE B C D BCD B B C BBBC