题意:给你一些单词和一个句子,问有多少个单词在这个句子上出现过。
AC自动机裸题
#include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <queue> using namespace std; const int maxn = 1000001; queue <int> q; struct Tree { int ch[maxn][28], fail[maxn], count[maxn], tot, root; void clear() { root = tot = 0; memset(ch, -1, sizeof(ch)); memset(fail, -1, sizeof(fail)); memset(count, 0, sizeof(count)); } void insert(char *str) { int x = root, len = strlen(str+1); for (int i = 1; i <= len; ++i) { int id = str[i]-'a'; if (ch[x][id] == -1) ch[x][id] = ++tot; x = ch[x][id]; } count[x] ++; } void build() { q.push(root); while (!q.empty()) { int x = q.front(); q.pop(); for (int i = 0; i < 26; ++i) if (ch[x][i] != -1) { if (x == root) fail[ch[x][i]] = root; else { int y = fail[x]; while (y != -1) { if (ch[y][i] != -1) { fail[ch[x][i]] = ch[y][i]; break ; } y = fail[y]; } if (y == -1) fail[ch[x][i]] = root; } q.push(ch[x][i]); } } } int find(char *str) { int x = root, len = strlen(str+1), ret = 0; for (int i = 1; i <= len; ++i) { int id = str[i]-'a'; while (ch[x][id] == -1 && x != root) x = fail[x]; x = ch[x][id]; if (x == -1) x = root; int y = x; while (y != root && count[y] != -1) { ret += count[y]; count[y] = -1; y = fail[y]; } } return ret; } }T; int n; char str[maxn]; int main() { int Case; scanf("%d", &Case); while (Case --) { T.clear(); scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%s", str+1); T.insert(str); } T.build(); scanf("%s", str+1); printf("%d ", T.find(str)); } return 0; }