题目链接:http://lightoj.com/volume_showproblem.php?problem=1427
题意:给定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 = 30;
const int N = 3e5 + 10;
const int M = 5e2 + 10;
const int INF = 0x7f7f7f7f;
const int MAX_WORD = 1e6 + 10;
const double EPS = 1e-9;
const int MOD = 2015;
int sz;
int ch[N][SIZE];
int f[N];
int val[N];
bool ed[N];
char txt[MAX_WORD];
char mod[M][M];
int newnode() {
memset(ch[sz], 0, sizeof(ch[sz]));
f[sz] = 0;
val[sz] = 0;
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++) {
int v = s[i] - 'a';
u = ch[u][v];
int t = u;
while (t) {
if (ed[t])
val[t]++;
t = f[t];
}
}
}
int main() {
int t_case;
scanf("%d", &t_case);
for (int i_case = 1; i_case <= t_case; i_case++) {
int n;
scanf("%d%s", &n, txt);
init();
for (int i = 0; i < n; i++) {
scanf("%s", mod[i]);
insert(mod[i]);
}
find(txt);
printf("Case %d:\n", i_case);
for (int i = 0; i < n; i++) {
int u = 0;
for (int j = 0; mod[i][j]; j++)
u = ch[u][mod[i][j] - 'a'];
printf("%d\n", val[u]);
}
}
return 0;
}