kyopro-lib

This documentation is automatically generated by online-judge-tools/verification-helper

View on GitHub

:x: test/yukicoder/430/main.aho_corasick.test.cpp

Depends on

Code

#define PROBLEM "https://yukicoder.me/problems/no/430"

#include <iostream>
#include <string>
#include <vector>
#include "Mylib/IO/input_vector.cpp"
#include "Mylib/String/aho_corasick.cpp"

namespace hl = haar_lib;

int main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);

  std::string S;
  std::cin >> S;
  int M;
  std::cin >> M;

  auto C = hl::input_vector<std::string>(M);

  hl::aho_corasick ac;
  for (int i = 0; i < M; ++i) {
    ac.add(C[i]);
  }

  ac.build();

  int ans = 0;
  ac.match(S, [&](int, int) { ++ans; });

  std::cout << ans << std::endl;

  return 0;
}
#line 1 "test/yukicoder/430/main.aho_corasick.test.cpp"
#define PROBLEM "https://yukicoder.me/problems/no/430"

#include <iostream>
#include <string>
#include <vector>
#line 4 "Mylib/IO/input_vector.cpp"

namespace haar_lib {
  template <typename T>
  std::vector<T> input_vector(int N) {
    std::vector<T> ret(N);
    for (int i = 0; i < N; ++i) std::cin >> ret[i];
    return ret;
  }

  template <typename T>
  std::vector<std::vector<T>> input_vector(int N, int M) {
    std::vector<std::vector<T>> ret(N);
    for (int i = 0; i < N; ++i) ret[i] = input_vector<T>(M);
    return ret;
  }
}  // namespace haar_lib
#line 2 "Mylib/String/aho_corasick.cpp"
#include <queue>
#line 4 "Mylib/String/aho_corasick.cpp"
#include <unordered_map>
#line 6 "Mylib/String/aho_corasick.cpp"

namespace haar_lib {
  class aho_corasick {
    int n_;
    std::vector<std::unordered_map<char, int>> trie_;
    std::vector<int> failure_edge_;
    std::vector<std::string> dict_;
    std::vector<std::vector<int>> dict_index_;

  public:
    aho_corasick() : n_(1), trie_(1), failure_edge_(1) {}

    void add(const std::string &s) {
      dict_.push_back(s);

      int cur = 0;

      for (int i = 0; i < (int) s.size(); ++i) {
        char c = s[i];

        if (trie_[cur].find(c) != trie_[cur].end()) {
          cur = trie_[cur][c];
        } else {
          ++n_;
          trie_.resize(n_);

          trie_[cur][c] = n_ - 1;

          cur = trie_[cur][c];
        }
      }

      dict_index_.resize(n_);
      dict_index_[cur].push_back(dict_.size() - 1);
    }

    void build() {
      failure_edge_.resize(n_);

      std::queue<int> dq;
      dq.push(0);

      while (not dq.empty()) {
        int cur = dq.front();
        dq.pop();

        for (auto &kv : trie_[cur]) {
          char c   = kv.first;
          int next = kv.second;

          if (cur == 0) {
            failure_edge_[next] = 0;

          } else {
            int i = failure_edge_[cur];
            int j = 0;

            while (1) {
              if (trie_[i].find(c) != trie_[i].end()) {
                j = trie_[i][c];
                break;
              } else {
                if (i == 0) break;
                i = failure_edge_[i];
              }
            }

            failure_edge_[next] = j;

            for (auto k : dict_index_[failure_edge_[next]]) {
              dict_index_[next].push_back(k);
            }
          }

          dq.push(next);
        }
      }
    }

    template <typename Func>  // function<void(int, int)>
    void match(const std::string &s, const Func &f) {
      int cur = 0;

      for (int i = 0; i < (int) s.size(); ++i) {
        const char c = s[i];

        while (cur != 0 and trie_[cur].find(c) == trie_[cur].end()) {
          cur = failure_edge_[cur];
        }

        cur = trie_[cur][c];

        for (auto j : dict_index_[cur]) {
          const int len = dict_[j].size();
          f(i - len + 1, len);
        }
      }
    }
  };
}  // namespace haar_lib
#line 8 "test/yukicoder/430/main.aho_corasick.test.cpp"

namespace hl = haar_lib;

int main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);

  std::string S;
  std::cin >> S;
  int M;
  std::cin >> M;

  auto C = hl::input_vector<std::string>(M);

  hl::aho_corasick ac;
  for (int i = 0; i < M; ++i) {
    ac.add(C[i]);
  }

  ac.build();

  int ans = 0;
  ac.match(S, [&](int, int) { ++ans; });

  std::cout << ans << std::endl;

  return 0;
}
Back to top page