题意:给你一个长度为n的单词表,一个文本串,问你这个文本串中出现了单词表中多少个单词;
思路:老模板题了,记录一下结尾字母累加就好了。
#include <bits/stdc++.h> using namespace std; const int N = 1e6 + 6; int n; namespace AC { int tr[N][26], tot; int e[N], fail[N]; void insert(char *s) { int u = 0; for (int i = 1; s[i]; i++) { if (!tr[u][s[i] - 'a']) tr[u][s[i] - 'a'] = ++tot; u = tr[u][s[i] - 'a']; } e[u]++; } queue<int> q; void build() { for (int i = 0; i < 26; i++) if (tr[0][i]) q.push(tr[0][i]); while (q.size()) { int u = q.front(); q.pop(); for (int i = 0; i < 26; i++) { if (tr[u][i]) fail[tr[u][i]] = tr[fail[u]][i], q.push(tr[u][i]); else tr[u][i] = tr[fail[u]][i]; } } } int query(char *t) { int u = 0, res = 0; for (int i = 1; t[i]; i++) { u = tr[u][t[i] - 'a']; // 转移 for (int j = u; j && e[j] != -1; j = fail[j]) { res += e[j], e[j] = -1; } } return res; } void init(){ memset(tr,0,sizeof(tr)); tot=0; memset(fail,0,sizeof(fail)); memset(e,0,sizeof(e)); } } // namespace AC char s[N]; int main() { int T; scanf("%d",&T); while(T--){ AC::init(); scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%s", s + 1), AC::insert(s); scanf("%s", s + 1); AC::build(); printf("%d ", AC::query(s)); } return 0; }