题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3065
题意:给定n个模式串,一个文本串,判断每个模式串中在文本串中出现的次数。
思路:AC自动机裸题。
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <stack>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define ceil(x, y) (((x) + (y) - 1) / (y))
const int SIZE = 55;
const int N = 5e4 + 10;
const int M = 1e3 + 10;
const int INF = 0x7f7f7f7f;
const int MAX_WORD = 2e6 + 10;
const double EPS = 1e-9;
const int MOD = 2015;
int sz;
int ch[N][SIZE];
int val[N];
bool vis[N], ed[N];
int f[N];
char model[M][SIZE];
char txt[MAX_WORD];
int newnode() {
memset(ch[sz], 0, sizeof(ch[sz]));
f[sz] = 0;
val[sz] = 0;
vis[sz] = false;
ed[sz] = false;
return sz++;
}
void init() {
sz = 0;
newnode();
}
void insert(char *s) {
int u = 0;
for (int i = 0; s[i]; i++) {
int v = s[i] - 'A';
if (!ch[u][v])
ch[u][v] = newnode();
u = ch[u][v];
}
ed[u] = true;
}
void getfail() {
queue<int> q;
for (int i = 0; i < SIZE; i++)
if (ch[0][i])
q.push(ch[0][i]);
while (!q.empty()) {
int r = q.front();
q.pop();
for (int i = 0; i < SIZE; i++) {
int v = ch[r][i];
if (v) {
q.push(v);
int u = f[r];
while (u && !ch[u][i]) u = f[u];
f[v] = ch[u][i];
}
else ch[r][i] = ch[f[r]][i];
}
}
}
void find(char *s) {
getfail();
int u = 0;
for (int i = 0; s[i]; i++) {
if (s[i] >= 'A' && s[i] <= 'Z') {
int v = s[i] - 'A';
u = ch[u][v];
if (ed[u])
val[u]++;
}
else u = 0;
}
}
int main() {
int n;
while (scanf("%d", &n) != EOF) {
init();
for (int i = 0; i < n; i++) {
scanf("%s", model[i]);
insert(model[i]);
}
scanf("%s", txt);
find(txt);
for (int i = 0; i < n; i++) {
int u = 0;
for (int j = 0; model[i][j]; j++) {
int v = model[i][j] - 'A';
u = ch[u][v];
}
if (val[u])
printf("%s: %d\n", model[i], val[u]);
}
}
return 0;
}