AC自动机
const int N = 1e5 + 5;
struct AC { vector<vector<int>> nex; vector<int> flag[N]; vector<int> fail; map<string, int> id; vector<int> cnt; vector<string> inv; int idx = 0; AC() { nex.resize(N, vector<int>(26)); fail.resize(N); cnt.resize(N); inv.resize(N); } void init() { for (int i = 0; i < N; i++) { for (int j = 0; j < 26; j++) { nex[i][j] = 0; } fail[i] = 0; } for (int i = 0; i < N; i++) { flag[i].clear(); cnt[i] = 0; }
id.clear(); inv.clear(); idx = 0; } void add(const string &s, int I) { id[s] = I; inv[I] = s; int p = 0; for (int i = 0; i < s.size(); i++) { int c = s[i] - 'a'; if (!nex[p][c]) nex[p][c] = ++idx; p = nex[p][c]; } flag[p].push_back(id[s]); } void get_fail() { queue<int> q; for (int i = 0; i < 26; i++) { if (nex[0][i]) q.push(nex[0][i]); } while (!q.empty()) { int x = q.front(); q.pop(); for (int i = 0; i < 26; i++) { if (nex[x][i]) { fail[nex[x][i]] = nex[fail[x]][i]; q.push(nex[x][i]); } else { nex[x][i] = nex[fail[x]][i]; } } } } void solve(const string &s) { get_fail(); int p = 0; for (int i = 0; i < s.size(); i++) { p = nex[p][s[i] - 'a']; for (int j = p; j; j = fail[j]) {
for (auto t : flag[j]) { cnt[t]++; } } } }} ac;// 每次新的 test 进入时要调用 init 函数// 对于每个模式串,调用 ac.add(t, idx)// 然后对于文本串调用 ac.solve(s)// 最终 cnt[idx] 代表的是对应的模式串出现的次数