結果
問題 | No.430 文字列検索 |
ユーザー | KowerKoint2010 |
提出日時 | 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 |
ソースコード
#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'; }