結果
問題 | No.430 文字列検索 |
ユーザー |
![]() |
提出日時 | 2024-08-31 17:29:04 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 15 ms / 2,000 ms |
コード長 | 4,551 bytes |
コンパイル時間 | 5,266 ms |
コンパイル使用メモリ | 301,268 KB |
実行使用メモリ | 8,452 KB |
最終ジャッジ日時 | 2024-11-10 01:13:09 |
合計ジャッジ時間 | 5,028 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 4 |
other | AC * 14 |
ソースコード
#include <bits/stdc++.h>using namespace std;using ll = long long;using P = pair<ll, ll>;#define rep(i, a, b) for(ll i = a; i < b; ++i)#define rrep(i, a, b) for(ll i = a; i >= b; --i)constexpr ll inf = 4e18;struct SetupIO {SetupIO() {ios::sync_with_stdio(0);cin.tie(0);cout << fixed << setprecision(30);}} setup_io;template <size_t X = 26, char margin = 'a'>struct Trie {struct Node {array<int, X> nxt;vector<int> idxs;int idx;int count;char key;Node(char c): idx(-1), count(0), key(c) {fill(nxt.begin(), nxt.end(), -1);}};vector<Node> st;Trie(char c = '$') {st.emplace_back(c);}inline int& next(int i, int j) {return st[i].nxt[j];}void insert(const string& s, int x) {int pos = 0;for(int i = 0; i < (int)s.size(); ++i) {++st[pos].count;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].count;st[pos].idx = x;st[pos].idxs.emplace_back(x);}int find(const string& s) {int pos = 0;for(int i = 0; i < (int)s.size(); ++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) {assert(pos < (int)st.size());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;}int count(int pos) {return pos < 0 ? 0 : st[pos].count;}vector<int> idxs(int pos) {return pos < 0 ? vector<int>() : st[pos].idxs;}};template <size_t X = 26, char margin = 'a', bool heavy = true>struct AhoCorasick : Trie<X + 1, margin> {using TRIE = Trie<X + 1, margin>;using TRIE::next;using TRIE::st;using TRIE::TRIE;vector<int> cnt;void build() {int n = (int)st.size();cnt.resize(n);for(int i = 0; i < n; ++i) {if(heavy) sort(st[i].idxs.begin(), st[i].idxs.end());cnt[i] = (int)st[i].idxs.size();}queue<int> que;for(int i = 0; i < (int)X; ++i) {if(~next(0, i)) {next(next(0, i), X) = 0;que.emplace(next(0, i));} else {next(0, i) = 0;}}while(!que.empty()) {auto& x = st[que.front()];int fail = x.nxt[X];cnt[que.front()] += cnt[fail];que.pop();for(int i = 0; i < (int)X; ++i) {int& nx = x.nxt[i];if(nx < 0) {nx = next(fail, i);continue;}que.emplace(nx);next(nx, X) = next(fail, i);if(heavy) {auto& idx = st[nx].idxs;auto& idy = st[next(fail, i)].idxs;vector<int> idz;set_union(idx.begin(), idx.end(), idy.begin(), idy.end(), back_inserter(idz));idx = idz;}}}}conditional_t<heavy, unordered_map<int, long long>, long long> match(const string& s) {unordered_map<int, int> pos_cnt;int pos = 0;for(const auto& c : s) {pos = next(pos, c - margin);++pos_cnt[pos];}conditional_t<heavy, unordered_map<int, long long>, long long> res{};for(const auto& [key, val] : pos_cnt) {if constexpr(heavy) {for(const auto& x : st[key].idxs) res[x] += val;} else {res += 1ll * cnt[key] * val;}}return res;}int count(int pos) {return cnt[pos];}};int main(void) {string S;int M;cin >> S >> M;AhoCorasick<26, 'A', true> aho;for(int i = 0; i < M; i++) {string T;cin >> T;aho.insert(T, i);}aho.build();unordered_map<int, ll> cnt = aho.match(S);int ans = 0;for(const auto& it : cnt) {ans += it.second;}cout << ans << '\n';}