結果

問題 No.430 文字列検索
ユーザー KowerKoint2010KowerKoint2010
提出日時 2024-12-03 11:13:19
言語 C++23
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 30 ms / 2,000 ms
コード長 2,185 bytes
コンパイル時間 3,103 ms
コンパイル使用メモリ 262,708 KB
実行使用メモリ 13,164 KB
最終ジャッジ日時 2024-12-03 11:13:24
合計ジャッジ時間 4,679 ms
ジャッジサーバーID
(参考情報)
judge5 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
5,248 KB
testcase_01 AC 30 ms
13,164 KB
testcase_02 AC 10 ms
9,216 KB
testcase_03 AC 10 ms
9,216 KB
testcase_04 AC 1 ms
5,248 KB
testcase_05 AC 2 ms
5,248 KB
testcase_06 AC 1 ms
5,248 KB
testcase_07 AC 2 ms
5,248 KB
testcase_08 AC 7 ms
6,016 KB
testcase_09 AC 2 ms
5,248 KB
testcase_10 AC 2 ms
5,248 KB
testcase_11 AC 17 ms
11,616 KB
testcase_12 AC 17 ms
12,016 KB
testcase_13 AC 18 ms
12,028 KB
testcase_14 AC 14 ms
10,880 KB
testcase_15 AC 13 ms
9,976 KB
testcase_16 AC 10 ms
9,844 KB
testcase_17 AC 11 ms
9,716 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;
template <class T>
using V = vector<T>;

struct ACTrie {
  using NP = ACTrie*;
  V<int> acc;
  map<int, NP> next;
  NP fail = nullptr, dnx = nullptr;

 private:
  void add(const string& s, int id, int p = 0) {
    if (p == int(s.size())) {
      acc.push_back(id);
      return;
    }
    if (next[s[p]] == nullptr) {
      next[s[p]] = new ACTrie();
    }
    next[s[p]]->add(s, id, p + 1);
  }
  template <class OP>
  NP count(OP op, int p) {
    if (fail == nullptr) return this;
    for (int id : acc) {
      op(id, p);
    }
    if (dnx) {
      dnx->count(op, p);
    } else {
      dnx = fail->count(op, p);
    }
    return acc.size() ? this : dnx;
  }

 public:
  // パターンにマッチするたびにop(string ID,
  // 発見位置の終端)を呼び出す
  // 終端が同じで複数マッチする文字列が存在する場合,⻑い順に呼び出される
  // s = "abaaba", pattern = {"ab", "ba"} なら
  // op(0, 2), op(1, 3), op(0, 5), op(1, 6)
  template <class OP>
  void match(const string& s, OP op, int p = 0) {
    if (p == int(s.size())) return;
    if (next[s[p]]) {
      next[s[p]]->count(op, p + 1);
      next[s[p]]->match(s, op, p + 1);
    } else {
      if (!fail)
        match(s, op, p + 1);  // root
      else
        fail->match(s, op, p);  // other
    }
  }
  static NP make(V<string> v) {
    NP tr = new ACTrie();
    for (int i = 0; i < int(v.size()); i++) {
      tr->add(v[i], i);
    }
    queue<NP> q;
    q.push(tr);
    tr->fail = nullptr;
    while (!q.empty()) {
      NP ntr = q.front();
      q.pop();
      for (auto p : ntr->next) {
        int i = p.first;
        NP fail = ntr->fail;
        while (fail && !fail->next.count(i)) {
          fail = fail->fail;
        }
        ntr->next[i]->fail =
            (fail == nullptr) ? tr : fail->next[i];
        q.push(ntr->next[i]);
      }
    }
    return tr;
  }
};

int main() {
    string s; cin >> s;
    int m; cin >> m;
    V<string> c(m);
    for(auto& cc : c) cin >> cc;
    auto aho = ACTrie::make(c);
    int ans = 0;
    auto op = [&](int , int) { ans++; };
    aho->match(s, op);
    cout << ans << '\n';
}

0