結果
問題 | No.430 文字列検索 |
ユーザー | 👑 emthrm |
提出日時 | 2020-11-05 23:27:59 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 10 ms / 2,000 ms |
コード長 | 4,415 bytes |
コンパイル時間 | 2,219 ms |
コンパイル使用メモリ | 217,472 KB |
実行使用メモリ | 7,676 KB |
最終ジャッジ日時 | 2024-11-10 00:48:36 |
合計ジャッジ時間 | 2,859 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 10 ms
7,676 KB |
testcase_02 | AC | 4 ms
5,248 KB |
testcase_03 | AC | 3 ms
5,248 KB |
testcase_04 | AC | 1 ms
5,248 KB |
testcase_05 | AC | 2 ms
5,248 KB |
testcase_06 | AC | 2 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 | 8 ms
5,596 KB |
testcase_12 | AC | 8 ms
5,756 KB |
testcase_13 | AC | 8 ms
5,760 KB |
testcase_14 | AC | 7 ms
5,468 KB |
testcase_15 | AC | 5 ms
5,600 KB |
testcase_16 | AC | 5 ms
5,464 KB |
testcase_17 | AC | 5 ms
5,596 KB |
ソースコード
#define _USE_MATH_DEFINES #include <bits/stdc++.h> using namespace std; #define FOR(i,m,n) for(int i=(m);i<(n);++i) #define REP(i,n) FOR(i,0,n) #define ALL(v) (v).begin(),(v).end() using ll = long long; constexpr int INF = 0x3f3f3f3f; constexpr long long LINF = 0x3f3f3f3f3f3f3f3fLL; constexpr double EPS = 1e-8; constexpr int MOD = 1000000007; // constexpr int MOD = 998244353; constexpr int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1}; constexpr int dy8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dx8[] = {0, -1, -1, -1, 0, 1, 1, 1}; template <typename T, typename U> inline bool chmax(T &a, U b) { return a < b ? (a = b, true) : false; } template <typename T, typename U> inline bool chmin(T &a, U b) { return a > b ? (a = b, true) : false; } struct IOSetup { IOSetup() { std::cin.tie(nullptr); std::ios_base::sync_with_stdio(false); std::cout << fixed << setprecision(20); } } iosetup; template <size_t char_sz = 26> struct Trie { struct Node { char c; int nx[char_sz]; std::vector<int> tails; Node(char c) : c(c) { std::memset(nx, -1, sizeof(nx)); } }; std::vector<Node> nodes; Trie(const char basis = 'a') : basis(basis) { nodes.emplace_back('$'); } void add(const std::string &s, int id = -1, int pos = 0) { for (char c : s) { int now = convert(c); if (nodes[pos].nx[now] == -1) { int nx_pos = nodes.size(); nodes[pos].nx[now] = nx_pos; nodes.emplace_back(c); pos = nx_pos; } else { pos = nodes[pos].nx[now]; } } nodes[pos].tails.emplace_back(id); } int find(const std::string &t, int pos = 0) const { for (char c : t) { int now = convert(c); if (nodes[pos].nx[now] == -1) return -1; pos = nodes[pos].nx[now]; } return pos; } int convert(char c) const { return c - basis; } private: const char basis; }; template <size_t char_sz = 26> struct AhoCorasick : Trie<char_sz + 1> { using Trie<char_sz + 1>::Trie; std::vector<int> cnt; void build(bool heavy = false) { is_built = true; is_heavy = heavy; auto &vertices = this->nodes; int n = vertices.size(); cnt.resize(n); for (int i = 0; i < n; ++i) { if (heavy) std::sort(vertices[i].tails.begin(), vertices[i].tails.end()); cnt[i] = vertices[i].tails.size(); } std::queue<int> que; for (int i = 0; i < char_sz; ++i) { if (vertices[0].nx[i] == -1) { vertices[0].nx[i] = 0; } else { vertices[vertices[0].nx[i]].nx[char_sz] = 0; que.emplace(vertices[0].nx[i]); } } while (!que.empty()) { auto node = vertices[que.front()]; cnt[que.front()] += cnt[node.nx[char_sz]]; que.pop(); for (int i = 0; i < char_sz; ++i) { if (node.nx[i] == -1) continue; int on_failure = node.nx[char_sz]; while (vertices[on_failure].nx[i] == -1) on_failure = vertices[on_failure].nx[char_sz]; vertices[node.nx[i]].nx[char_sz] = vertices[on_failure].nx[i]; if (heavy) { std::vector<int> &ver = vertices[node.nx[i]].tails, tmp; std::set_union(ver.begin(), ver.end(), vertices[vertices[on_failure].nx[i]].tails.begin(), vertices[vertices[on_failure].nx[i]].tails.end(), std::back_inserter(tmp)); ver.resize(tmp.size()); std::copy(tmp.begin(), tmp.end(), ver.begin()); } que.emplace(node.nx[i]); } } } int move(char c, int pos) const { // assert(is_built); int now = this->convert(c); while (this->nodes[pos].nx[now] == -1) pos = this->nodes[pos].nx[char_sz]; return pos = this->nodes[pos].nx[now]; } int match(const std::string &t, int pos = 0) const { assert(is_built); int total = 0; for (char c : t) { pos = move(c, pos); total += cnt[pos]; } return total; } std::map<int, int> match_heavy(const std::string &t, int pos = 0) const { assert(is_built && is_heavy); std::map<int, int> mp; for (char c : t) { pos = move(c, pos); for (int e : this->nodes[pos].tails) ++mp[e]; } return mp; } private: bool is_built = false, is_heavy = false; }; int main() { std::string s; std::cin >> s; AhoCorasick<> aho('A'); int m; std::cin >> m; for (int i = 0; i < m; ++i) { std::string p; std::cin >> p; aho.add(p, i); } aho.build(); std::cout << aho.match(s) << '\n'; return 0; }