結果
問題 | No.430 文字列検索 |
ユーザー | tokusakurai |
提出日時 | 2020-10-26 12:38:18 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 15 ms / 2,000 ms |
コード長 | 4,667 bytes |
コンパイル時間 | 2,472 ms |
コンパイル使用メモリ | 216,304 KB |
実行使用メモリ | 7,804 KB |
最終ジャッジ日時 | 2024-11-10 00:48:18 |
合計ジャッジ時間 | 2,818 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 15 ms
7,804 KB |
testcase_02 | AC | 6 ms
5,248 KB |
testcase_03 | AC | 6 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 | 2 ms
5,248 KB |
testcase_08 | AC | 3 ms
5,248 KB |
testcase_09 | AC | 2 ms
5,248 KB |
testcase_10 | AC | 2 ms
5,248 KB |
testcase_11 | AC | 11 ms
6,036 KB |
testcase_12 | AC | 11 ms
6,408 KB |
testcase_13 | AC | 11 ms
6,412 KB |
testcase_14 | AC | 10 ms
5,672 KB |
testcase_15 | AC | 8 ms
5,540 KB |
testcase_16 | AC | 7 ms
5,408 KB |
testcase_17 | AC | 8 ms
5,412 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; #define rep(i, n) for(int i = 0; i < n; i++) #define rep2(i, x, n) for(int i = x; i <= n; i++) #define rep3(i, x, n) for(int i = x; i >= n; i--) #define elif else if #define sp(x) fixed << setprecision(x) #define pb push_back #define eb emplace_back #define all(x) x.begin(), x.end() #define sz(x) (int)x.size() using ll = long long; using pii = pair<int, int>; using pil = pair<int, ll>; using pli = pair<ll, int>; using pll = pair<ll, ll>; const int MOD = 1000000007; //const int MOD = 998244353; const int inf = (1<<30)-1; const ll INF = (1LL<<60)-1; const double pi = acos(-1.0); const double EPS = 1e-10; template<typename T> bool chmax(T &x, const T &y) {return (x < y)? (x = y, true) : false;}; template<typename T> bool chmin(T &x, const T &y) {return (x > y)? (x = y, true) : false;}; //Aho-Corasick法(複数文字列についてパターンマッチするオートマトンを構築する) //計算量 構築:O(∑|S[i]|)、遷移:O(1) template<int char_size, char base> struct Trie{ struct Node{ vector<int> next, accept; int count; //子以下に追加された文字列の数 Node() : count(0){ next.assign(char_size, -1); } }; vector<Node> nodes; Trie() {nodes.eb();} int count() const {return nodes.front().count;} int size() const {return sz(nodes);} void insert(const string &s, int id){ int now = 0; rep(i, sz(s)){ int &next = nodes[now].next[s[i]-base]; if(next == -1){ next = size(), nodes.eb(); } nodes[now].count++, now = next; } nodes[now].count++, nodes[now].accept.pb(id); } void insert(const string &s) {insert(s, count());} bool search(const string &s, bool prefix = false) const{ int now = 0; rep(i, sz(s)){ now = nodes[now].next[s[i]-base]; if(now == -1) return false; } return (prefix)? true : !nodes[now].accept.empty(); } }; template<int char_size, char base> struct Aho_Corasick : Trie<char_size+1, base>{ using trie = Trie<char_size+1, base>; const int FAIL = char_size; vector<int> correct; void build(bool heavy = true){ correct.resize(this->size()); rep(i, this->size()){ correct[i] = sz(this->nodes[i].accept); } queue<int> que; rep(i, char_size+1){ if(this->nodes[0].next[i] != -1){ this->nodes[this->nodes[0].next[i]].next[FAIL] = 0; que.push(this->nodes[0].next[i]); } else{ this->nodes[0].next[i] = 0; } } while(!que.empty()){ auto &now = this->nodes[que.front()]; int fail = now.next[FAIL]; correct[que.front()] += correct[fail]; que.pop(); rep(i, char_size){ if(now.next[i] != -1){ this->nodes[now.next[i]].next[FAIL] = this->nodes[fail].next[i]; if(heavy){ auto &u = this->nodes[now.next[i]].accept; auto &v = this->nodes[this->nodes[fail].next[i]].accept; vector<int> accept; set_union(all(u), all(v), back_inserter(accept)); u = accept; } que.emplace(now.next[i]); } else{ now.next[i] = this->nodes[fail].next[i]; } } } } map<int, int> match(int now, const string &s) const{ map<int, int> ret; for(auto &c: s){ now = this->nodes[now].next[c-base]; for(auto &u: this->nodes[now].accept) ret[u]++; } return ret; } map<int, int> match(const string &s) const {return match(0, s);} pli move(int now, const char &c) const{ now = this->nodes[now].next[c-base]; return pli(correct[now], now); } pli move(const char &c) const {return move(0, c);} pli move(int now, const string &s) const{ ll sum = 0; for(auto &c: s){ pli p = move(now, c); sum += p.first, now = p.second; } return pli(sum, now); } pli move(const string &s) const {return move(0, s);} }; //https://yukicoder.me/problems/no/1269 int main(){ string S; int N; cin >> S >> N; Aho_Corasick<26, 'A'> aho; rep(i, N){ string t; cin >> t; aho.insert(t); } aho.build(); cout << aho.move(S).first << endl; }