結果
| 問題 |
No.430 文字列検索
|
| コンテスト | |
| ユーザー |
629e^-b
|
| 提出日時 | 2021-04-28 12:37:59 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 13 ms / 2,000 ms |
| コード長 | 3,969 bytes |
| コンパイル時間 | 4,423 ms |
| コンパイル使用メモリ | 257,520 KB |
| 最終ジャッジ日時 | 2025-01-21 01:40:38 |
|
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 14 |
ソースコード
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int, int>;
using pdd = pair<double, double>;
using pll = pair<ll, ll>;
using pli = pair<ll, int>;
using pil = pair<int, ll>;
template <typename T>
using Graph = vector<vector<T>>;
const int MOD = 1e9 + 7;
const ld PI = acos(-1);
template <int char_size, int base>
struct Trie {
struct Node {
Node *next[char_size];
int exist;
vector<int> accept;
Node() : exist(0) {
memset(next, 0, sizeof(next));
}
~Node() {
for (int i = 0; i < char_size; ++i) {
if (next[i] != nullptr) {
delete next[i];
}
}
}
};
Node *root;
int size;
Trie() : root(new Node), size(1) {}
void add(const string &str, int id) {
Node *now = root;
for (int i = 0; i < str.size(); ++i) {
int c = str[i] - base;
if (now->next[c] == nullptr) {
now->next[c] = new Node;
size++;
}
(now->exist)++;
now = now->next[c];
}
(now->exist)++;
now->accept.emplace_back(id);
}
void add(const string &str) {
add(str, root->exist);
}
bool query(const string &str, bool prefix = false) {
Node *now = root;
for (int i = 0; i < str.size(); ++i) {
int c = str[i] - base;
if (now->next[c] == nullptr)
return false;
now = now->next[c];
}
return prefix | (now->accept.size() > 0);
}
int count() const {
return root->exist;
}
};
template <int char_size, int base>
struct AhoCorasick : Trie<char_size + 1, base> {
using typename Trie<char_size + 1, base>::Node;
const int FAIL = char_size;
void build() {
queue<Node *> que;
for (int i = 0; i <= char_size; ++i) {
Node *&next_node = this->root->next[i];
if (next_node != nullptr) {
next_node->next[FAIL] = this->root;
que.emplace(next_node);
} else {
next_node = this->root;
}
}
while (!que.empty()) {
Node *now = que.front();
Node *fail_node = now->next[FAIL];
que.pop();
for (int i = 0; i < char_size; ++i) {
if (now->next[i] == nullptr) {
now->next[i] = fail_node->next[i];
continue;
}
while (fail_node->next[i] == nullptr)
fail_node = fail_node->next[FAIL];
now->next[i]->next[FAIL] = fail_node->next[i];
vector<int> accept;
vector<int> &u = now->next[i]->accept;
vector<int> &v = fail_node->next[i]->accept;
set_union(u.begin(), u.end(), v.begin(), v.end(), back_inserter(accept));
swap(u, accept);
que.push(now->next[i]);
}
}
}
vector<int> match(const string &str) {
Node *now = this->root;
vector<int> res(this->count());
for (int i = 0; i < str.size(); ++i) {
int c = str[i] - base;
now = now->next[c];
for (int j = 0; j < now->accept.size(); ++j) {
res[now->accept[j]]++;
}
}
return res;
}
};
int main() {
cin.tie(0);
ios::sync_with_stdio(false);
string S;
cin >> S;
int M;
cin >> M;
AhoCorasick<26, 'A'> ahc;
for (int i = 0; i < M; ++i) {
string C;
cin >> C;
ahc.add(C);
}
ahc.build();
auto res = ahc.match(S);
ll ans = 0;
for (auto i : res) {
ans += i;
}
cout << ans << endl;
return 0;
}
629e^-b