SlideShare a Scribd company logo
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

PDF
Aho corasick-lecture
ODP
Regex Presentation
PPT
Regular Expressions
PPT
Lec 02 data representation part 1
PPTX
Unit iv
PDF
Neural Architectures for Named Entity Recognition
PPTX
AtCoder Beginner Contest 012 解説
Aho corasick-lecture
Regex Presentation
Regular Expressions
Lec 02 data representation part 1
Unit iv
Neural Architectures for Named Entity Recognition
AtCoder Beginner Contest 012 解説

What's hot (20)

PPTX
Naming Standards, Clean Code
PPT
Genetic Algorithms - GAs
PPTX
NAMED ENTITY RECOGNITION
PPT
アルゴリズムイントロダクション15章 動的計画法
PDF
Bubblesort Algorithm
PDF
AVX2時代の正規表現マッチング 〜半群でぐんぐん!〜
PPTX
Regular expressions
PPSX
Deadlock ss
PDF
Rough K Means - Numerical Example
PPTX
daa-unit-3-greedy method
PPTX
BINARY SEARCH TREE
PPT
Expert Systems & Prolog
PPTX
Regular Expression (Regex) Fundamentals
PPTX
Computational Complexity
PPTX
AtCoderに毎回参加したくなる仕組み
PPTX
MT6702 Unit 2 Random Number Generation
PPT
Evolutionary-Algorithms.ppt
PDF
SATySFi 最近の発展と目下実装中の変更
Naming Standards, Clean Code
Genetic Algorithms - GAs
NAMED ENTITY RECOGNITION
アルゴリズムイントロダクション15章 動的計画法
Bubblesort Algorithm
AVX2時代の正規表現マッチング 〜半群でぐんぐん!〜
Regular expressions
Deadlock ss
Rough K Means - Numerical Example
daa-unit-3-greedy method
BINARY SEARCH TREE
Expert Systems & Prolog
Regular Expression (Regex) Fundamentals
Computational Complexity
AtCoderに毎回参加したくなる仕組み
MT6702 Unit 2 Random Number Generation
Evolutionary-Algorithms.ppt
SATySFi 最近の発展と目下実装中の変更
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
I want help in the following C++ programming task. Please do coding .pdf
PPTX
15. map, unordered map, algorithms
PDF
maincpp include ListItemh include ltstringgt in.pdf
PDF
Need help with the TODO's (DONE IN C++) #pragma once #include -funct.pdf
PPTX
C++11 - STL Additions
KEY
Brunhild
PPTX
DS Assignment Presentation 20242024.pptx
PPTX
Advanced data structure
PDF
String searching
PDF
Rcpp11 genentech
PDF
An Introduction to Part of C++ STL
PDF
R/C++ talk at earl 2014
PDF
Coscup2021-rust-toturial
PDF
MAINCPP include ltiostreamgt include ltstringgt u.pdf
PPTX
Object Oriented Programming Using C++: C++ STL Programming.pptx
PDF
In C++ Follow all code styling and submission instructions a.pdf
PDF
Generic programming and concepts that should be in C++
PPTX
14. containers, vector, list
PPTX
11. template
PPTX
C++11 - A Change in Style - v2.0
I want help in the following C++ programming task. Please do coding .pdf
15. map, unordered map, algorithms
maincpp include ListItemh include ltstringgt in.pdf
Need help with the TODO's (DONE IN C++) #pragma once #include -funct.pdf
C++11 - STL Additions
Brunhild
DS Assignment Presentation 20242024.pptx
Advanced data structure
String searching
Rcpp11 genentech
An Introduction to Part of C++ STL
R/C++ talk at earl 2014
Coscup2021-rust-toturial
MAINCPP include ltiostreamgt include ltstringgt u.pdf
Object Oriented Programming Using C++: C++ STL Programming.pptx
In C++ Follow all code styling and submission instructions a.pdf
Generic programming and concepts that should be in C++
14. containers, vector, list
11. template
C++11 - A Change in Style - v2.0

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