結果
問題 | No.430 文字列検索 |
ユーザー | lowr |
提出日時 | 2019-08-09 22:34:51 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 165 ms / 2,000 ms |
コード長 | 4,667 bytes |
コンパイル時間 | 1,882 ms |
コンパイル使用メモリ | 211,104 KB |
実行使用メモリ | 9,360 KB |
最終ジャッジ日時 | 2024-08-15 16:19:07 |
合計ジャッジ時間 | 2,851 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 165 ms
6,812 KB |
testcase_01 | AC | 1 ms
6,940 KB |
testcase_02 | AC | 9 ms
9,360 KB |
testcase_03 | AC | 5 ms
6,940 KB |
testcase_04 | AC | 5 ms
6,944 KB |
testcase_05 | AC | 1 ms
6,940 KB |
testcase_06 | AC | 2 ms
6,944 KB |
testcase_07 | AC | 1 ms
6,940 KB |
testcase_08 | AC | 1 ms
6,944 KB |
testcase_09 | AC | 3 ms
6,940 KB |
testcase_10 | AC | 1 ms
6,944 KB |
testcase_11 | AC | 2 ms
6,940 KB |
testcase_12 | AC | 8 ms
7,868 KB |
testcase_13 | AC | 8 ms
8,008 KB |
testcase_14 | AC | 9 ms
8,256 KB |
testcase_15 | AC | 6 ms
7,704 KB |
testcase_16 | AC | 6 ms
6,940 KB |
testcase_17 | AC | 5 ms
6,944 KB |
testcase_18 | AC | 6 ms
6,940 KB |
ソースコード
#include <bits/stdc++.h> using i64 = long long; namespace Trie { template <unsigned alphabet_size> struct Node { Node *next[alphabet_size]; unsigned exist; std::vector<int> accept; Node() : next(), exist(0) {} }; template <unsigned alphabet_size> class NodePool { unsigned pool_size; unsigned pos; std::allocator<Node<alphabet_size>> alc; Node<alphabet_size> *pool; public: NodePool(unsigned size) : pool_size(size), pos(0), pool(alc.allocate(pool_size)) {} ~NodePool() { for (unsigned i = 0; i < pos; i++) pool[pos - 1 - i].~Node(); alc.deallocate(pool, pool_size); } auto alloc() { return new(pool + pos++) Node<alphabet_size>(); } }; template <unsigned alphabet_size = 26, unsigned margin = 'a'> struct Trie { NodePool<alphabet_size> pool; Node<alphabet_size> *root; void add_impl(const std::string &str, unsigned id) { auto node = root; for (unsigned c : str) { c -= margin; if (node->next[c] == nullptr) { node->next[c] = pool.alloc(); } node->exist++; node = node->next[c]; } node->accept.push_back(id); } // maximum size of node pool explicit Trie(unsigned max_pool_size) : pool(max_pool_size), root(pool.alloc()) {} void add(const std::string &str) { add_impl(str, root->exist); } }; template <unsigned alphabet_size = 26, unsigned margin = 'a'> struct AhoCorasick : Trie<alphabet_size + 2, margin> { using TrieF = Trie<alphabet_size + 2, margin>; using NodeF = Node<alphabet_size + 2>; using TrieF::root; static constexpr unsigned failure = alphabet_size; static constexpr unsigned prefix = failure + 1; AhoCorasick(unsigned max_pool_size) : TrieF(max_pool_size) {} // build pattern matching automaton from trie void build() { std::deque<NodeF *> q { root }; root->next[failure] = root; while (!q.empty()) { auto node = q.front(); q.pop_front(); for (unsigned c = 0; c < alphabet_size; c++) { if (node->next[c] == nullptr) continue; q.push_back(node->next[c]); auto fail_next = node->next[failure]; while (fail_next->next[c] == nullptr && fail_next != root) { fail_next = fail_next->next[failure]; } node->next[c]->next[failure] = fail_next->next[c] && fail_next != node ? fail_next->next[c] : root; auto t = node->next[c]->next[failure]; node->next[c]->next[prefix] = t->accept.size() ? t : t->next[prefix]; } } } auto transition(NodeF *node, unsigned c) { c -= margin; while (node->next[c] == nullptr && node != root) { node = node->next[failure]; } return node->next[c] ? node->next[c] : node; } auto match(const std::string &str) { std::vector<int> ret(root->exist); auto node = root; for (unsigned c : str) { node = transition(node, c); auto t = node; while (t && t != root) { for (auto w : t->accept) ret[w]++; t = t->next[prefix]; } } return ret; } // F: (id: unsigned, r: unsigned) -> void // [r - length, r) template <typename F> void match_apply(const std::string &str, const F &f) { auto node = root; for (std::size_t i = 0; i < str.size(); i++) { node = transition(node, str[i]); auto t = node; while (t && t != root) { for (auto w : t->accept) f(w, i + 1); t = t->next[prefix]; } } } }; } int main() { std::string s; int m; std::cin >> s >> m; std::vector<std::string> c(m); Trie::AhoCorasick<26, 'A'> ac(50000); for (auto &e : c) { std::cin >> e; ac.add(e); } ac.build(); auto v = ac.match(s); std::cout << std::accumulate(v.begin(), v.end(), 0ll) << std::endl; return 0; }