又一AC自动机模板题...
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <iostream>
#include <sstream>
#define ll long long
using namespace std;
struct AcAutoMachine {
#define N 50005 // 字典的节点数,比最大数据略大即可
#define M 26 // 字典的字母数,此为精确值
int next[N][M], fail[N], data[N], size, cunt;
int queu[N], reco[1005], head, tail;
int code(const char &c) { // 将字符哈希成结点标号
if (c >= 'A' && c <= 'Z')
return c - 'A';
else
return -1;
}
void clear(int x) {
memset(next[x], -1, sizeof(next[x]));
fail[x] = -1; data[x] = 0;
}
void init() {
clear(0);
size = cunt = 1;
memset(reco, 0, sizeof(reco));
}
void insert(char *str) {
int p = 0, idx;
while (*str) {
idx = code(*str);
if (next[p][idx] == -1) {
clear(size);
next[p][idx] = size++;
}
p = next[p][idx];
str++;
}
data[p] = cunt++;
}
void buildac() {
int p, pp, fp, fpp;
head = tail = 0;
queu[tail++] = 0;
while (head < tail) {
p = queu[head++];
for (int i = 0; i < M; i++) {
if ((pp = next[p][i]) != -1) {
for (fp = fail[p]; fp != -1; fp = fail[fp]) {
if ((fpp = next[fp][i]) != -1) {
fail[pp] = fpp;
// 将fail链上后继结点的权值加到前驱结点中,
// 这样计算权值时就不需要遍历fail链,看情况是否需要。
// data[pp] += data[fpp];
break;
}
}
if (fp == -1) fail[pp] = 0;
queu[tail++] = pp;
} else { // 重构next,看题目是否需要
if (p == 0) next[p][i] = 0;
else next[p][i] = next[fail[p]][i];
}
}
}
}
void query(char *str) {
int p = 0, ret = 0, idx, pp;
while (*str) {
idx = code(*str);
if (idx == -1) {
p = 0;
} else {
p = next[p][idx];
for (pp = p; pp != -1; pp = fail[pp]) {
ret += data[pp];
if (data[pp]) reco[data[pp]]++;
}
}
++str;
}
}
} A;
char name[1005][51];
char str[2000005];
int main() {
int n, i;
while (scanf("%d", &n) != EOF) {
A.init();
for (i = 1; i <= n; i++) {
scanf("%s", name[i]);
A.insert(name[i]);
}
A.buildac();
getchar();
gets(str);
A.query(str);
for (i = 1; i <= n; i++)
if (A.reco[i]) printf("%s: %d\n", name[i], A.reco[i]);
}
return 0;
}