結果
問題 | No.430 文字列検索 |
ユーザー | kusaf_ |
提出日時 | 2024-11-03 02:41:30 |
言語 | C++23 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 10 ms / 2,000 ms |
コード長 | 3,293 bytes |
コンパイル時間 | 3,538 ms |
コンパイル使用メモリ | 273,388 KB |
実行使用メモリ | 8,000 KB |
最終ジャッジ日時 | 2024-11-10 01:13:48 |
合計ジャッジ時間 | 3,577 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1 ms
5,248 KB |
testcase_01 | AC | 10 ms
8,000 KB |
testcase_02 | AC | 4 ms
5,248 KB |
testcase_03 | AC | 4 ms
5,248 KB |
testcase_04 | AC | 2 ms
5,248 KB |
testcase_05 | AC | 2 ms
5,248 KB |
testcase_06 | AC | 1 ms
5,248 KB |
testcase_07 | AC | 1 ms
5,248 KB |
testcase_08 | AC | 2 ms
5,248 KB |
testcase_09 | AC | 2 ms
5,248 KB |
testcase_10 | AC | 1 ms
5,248 KB |
testcase_11 | AC | 7 ms
5,760 KB |
testcase_12 | AC | 7 ms
5,700 KB |
testcase_13 | AC | 7 ms
5,824 KB |
testcase_14 | AC | 7 ms
5,632 KB |
testcase_15 | AC | 6 ms
5,756 KB |
testcase_16 | AC | 5 ms
5,760 KB |
testcase_17 | AC | 5 ms
5,628 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; template<size_t X = 26, char margin = 'a'> struct Trie { struct Node { array<int, X> nxt; vector<int> idxs; int idx; char key; Node(char c): idx(-1), key(c) { ranges::fill(nxt, -1); } }; int c = 0; vector<Node> st; Trie() { st.emplace_back('$'); } Trie(const vector<string> &v) { st.emplace_back('$'); for(auto &i : v) { insert(i); } } void clear() { st.clear(); st.emplace_back('$'); } inline int &next(int i, int j) { return st[i].nxt[j]; } void insert(const string &s) { int pos = 0; for(int i = 0; i < ssize(s); i++) { int k = s[i] - margin; if(~next(pos, k)) { pos = next(pos, k); continue; } int npos = st.size(); next(pos, k) = npos; st.emplace_back(s[i]); pos = npos; } st[pos].idx = c; st[pos].idxs.emplace_back(c); c++; } int find(const string &s) { int pos = 0; for(int i = 0; i < ssize(s); i++) { int k = s[i] - margin; if(next(pos, k) < 0) { return -1; } pos = next(pos, k); } return pos; } int move(int pos, char c) { return pos < 0 ? -1 : next(pos, c - margin); } int size() const { return st.size(); } int idx(int pos) { return pos < 0 ? -1 : st[pos].idx; } vector<int> idxs(int pos) { return pos < 0 ? vector<int>() : st[pos].idxs; } }; template<size_t X = 26, char margin = 'a'> struct AhoCorasick : Trie<X + 1, margin> { using TRIE = Trie<X + 1, margin>; using TRIE::c; using TRIE::next; using TRIE::st; using TRIE::TRIE; vector<int> cnt; void build(bool heavy = false) { int n = st.size(); cnt.resize(n); for(int i = 0; i < n; i++) { if(heavy) { ranges::sort(st[i].idxs); } cnt[i] = st[i].idxs.size(); } queue<int> q; for(int i = 0; i < (int)X; i++) { if(~next(0, i)) { next(next(0, i), X) = 0; q.emplace(next(0, i)); } else { next(0, i) = 0; } } while(!q.empty()) { auto &x = st[q.front()]; int fail = x.nxt[X]; cnt[q.front()] += cnt[fail]; q.pop(); for(int i = 0; i < (int)X; i++) { int &nx = x.nxt[i]; if(nx < 0) { nx = next(fail, i); continue; } q.emplace(nx); next(nx, X) = next(fail, i); if(heavy) { auto &idx = st[nx].idxs, &idy = st[next(fail, i)].idxs; vector<int> idz; ranges::set_union(idx, idy, back_inserter(idz)); idx = idz; } } } } ll match_count(string s) { int res = 0, pos = 0; for(auto &c : s) { pos = next(pos, c - margin); res += cnt[pos]; } return res; } vector<vector<int>> match(string s) { vector<vector<int>> res(c); int pos = 0; for(int i = 0; i < (int)s.size(); i++) { pos = next(pos, s[i] - margin); for(auto &x : st[pos].idxs) { res[x].emplace_back(i); } } return res; } int count(int pos) { return cnt[pos]; } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); ll N; string S; cin >> S >> N; AhoCorasick<26, 'A'> A; while(N--) { string t; cin >> t; A.insert(t); } A.build(); cout << A.match_count(S) << "\n"; }