結果
| 問題 |
No.430 文字列検索
|
| コンテスト | |
| ユーザー |
shinchan
|
| 提出日時 | 2025-10-29 17:09:40 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 17 ms / 2,000 ms |
| コード長 | 4,715 bytes |
| コンパイル時間 | 3,322 ms |
| コンパイル使用メモリ | 291,536 KB |
| 実行使用メモリ | 8,896 KB |
| 最終ジャッジ日時 | 2025-10-29 17:09:45 |
| 合計ジャッジ時間 | 4,779 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 14 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb emplace_back
#define rep(i, n) for(int i=0;i<(n);i++)
#define foa(e, v) for(auto& e : v)
#define dout(a) cout<<fixed<<setprecision(10)<<a<<'\n';
#define Cout(a) cout<<a<<'\n';
using ll = long long;
using ld = long double;
using Int = __int128;
template <class T> using pqr = priority_queue<T, vector<T>, greater<T>>;
template <typename T1, typename T2> inline bool chmax(T1 &a, T2 b) {
bool compare = a < b;
if(compare) a = b;
return compare;
}
template <typename T1, typename T2> inline bool chmin(T1 &a, T2 b) {
bool compare = a > b;
if(compare) a = b;
return compare;
}
template <typename T> inline T back(std::set<T> &s) {
return *s.rbegin();
}
template <typename T> inline T back(std::multiset<T> &s) {
return *s.rbegin();
}
template <typename T> inline T pop_back(std::set<T> &s) {
auto it = prev(s.end());
T val = *it;
s.erase(it);
return val;
}
template <typename T> inline T pop_back(std::multiset<T> &s) {
auto it = prev(s.end());
T val = *it;
s.erase(it);
return val;
}
const int dy[8] = {-1, 0, 0, 1, 1, -1, 1, -1};
const int dx[8] = {0, -1, 1, 0, -1, -1, 1, 1};
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (3LL << 59);
const int inf = 1 << 30;
const char br = '\n';
template<int char_size> struct TrieNode {
int nxt[char_size];
int exist;
vector<int> accept;
TrieNode() : exist(0) { memset(nxt, -1, sizeof(nxt)); }
};
template<int char_size, int margin> struct Trie {
using Node = TrieNode<char_size>;
vector<Node> nodes;
int root;
Trie() : root(0) { nodes.push_back(Node()); }
void add(const string& str, int str_index, int node_index, int id) {
if(str_index == size(str)) {
nodes[node_index].accept.push_back(id);
} else {
const int c = str[str_index] - margin;
if(nodes[node_index].nxt[c] == -1) {
nodes[node_index].nxt[c] = size(nodes);
nodes.push_back(Node());
}
add(str, str_index + 1, nodes[node_index].nxt[c], id);
nodes[node_index].exist ++;
}
}
void add(const string& str, int id = -1) {
if(id == -1) id = nodes[0].exist;
add(str, 0, 0, id);
}
};
template<int char_size, int margin> struct AhoCorasick : Trie<char_size + 1, margin> {
using Trie<char_size + 1, margin>::Trie;
const int FAIL = char_size;
vector<int> correct;
void build(bool heavy = true) {
correct.resize(this->nodes.size());
for(int i = 0; i < size(this->nodes); ++i) { correct[i] = size(this->nodes[i].accept); }
queue<int> que;
for(int i = 0; i < char_size; ++i) {
if(~this->nodes[0].nxt[i]) {
this->nodes[this->nodes[0].nxt[i]].nxt[FAIL] = 0;
que.emplace(this->nodes[0].nxt[i]);
} else {
this->nodes[0].nxt[i] = 0;
}
}
while(!que.empty()) {
auto& now = this->nodes[que.front()];
int fail = now.nxt[FAIL];
correct[que.front()] += correct[fail];
que.pop();
for(int i = 0; i < char_size; i++) {
if(~now.nxt[i]) {
this->nodes[now.nxt[i]].nxt[FAIL] = this->nodes[fail].nxt[i];
if(heavy) {
auto& u = this->nodes[now.nxt[i]].accept;
auto& v = this->nodes[this->nodes[fail].nxt[i]].accept;
vector<int> accept;
set_union(all(u), all(v), back_inserter(accept));
u = accept;
}
que.emplace(now.nxt[i]);
} else {
now.nxt[i] = this->nodes[fail].nxt[i];
}
}
}
}
vector<int> match(const char& c, int now = 0) {
vector<int> res;
now = this->nodes[now].nxt[c - margin];
for(auto& v : this->nodes[now].accept) res.push_back(v);
return res;
}
unordered_map<int, int> match(const string& str, int now = 0) {
unordered_map<int, int> res, visit_cnt;
for(auto& c : str) {
now = this->nodes[now].nxt[c - margin];
visit_cnt[now]++;
}
for(auto& [now, cnt] : visit_cnt) {
for(auto& v : this->nodes[now].accept) res[v] += cnt;
}
return res;
}
pair<ll, int> move(const char& c, int now = 0) {
now = this->nodes[now].nxt[c - margin];
return {correct[now], now};
}
};
void solve() {
string S;
cin >> S;
int M;
cin >> M;
AhoCorasick<26, 'A'> aho;
for(int i = 0; i < M; i++) {
string s;
cin >> s;
aho.add(s);
}
aho.build();
ll sum = 0;
int now = 0;
foa(e, S) {
auto [cnt, nx] = aho.move(e, now);
sum += cnt;
now = nx;
}
cout << sum << endl;
}
int main() {
cin.tie(0);
ios::sync_with_stdio(false);
int testcase = 1;
// cin >> testcase;
while(testcase --) solve();
return 0;
}
shinchan