前言
AC自动机模板题,第一次ACAC自动机的题目,感动。
一些点需要注意:
测试样例会有多个
开结构体数组得开多点(50*maxn),为什么是50我也不清楚
不然会不断的RE-TLE-MLE
一、题目
题目链接: hdu3065
input:
3
AA
BB
CC
ooxxCC%dAAAoen....END
output:
AA: 2
CC: 1
二、代码
#include <cstring>
#include <iostream>
#include <queue>
#include <string>
using namespace std;
const int maxn = 1111 * 50;
const int maxm = 2e6 + 6;
struct node {
int id;
int son[30];
void init() {
id = 0;
memset(son, 0, sizeof(son));
}
};
node trie[maxn];
int cnt, fail[maxn];
char str[maxm];
char virus[maxn][60];
int ans[maxn];
void insert(char *s, int x) {
int len = strlen(s);
int cur = 0;
for (int i = 0; i < len; i++) {
int c = s[i] - 'A';
if (!trie[cur].son[c]) {
trie[cur].son[c] = ++cnt;
trie[cnt].init();
}
cur = trie[cur].son[c];
}
trie[cur].id = x;
}
void getfail() {
queue<int> q;
for (int i = 0; i < 26; i++) {
if (trie[0].son[i]) {
fail[trie[0].son[i]] = 0;
q.push(trie[0].son[i]);
}
}
while (!q.empty()) {
int cur = q.front();
q.pop();
for (int i = 0; i < 26; i++) {
if (trie[cur].son[i]) {
fail[trie[cur].son[i]] = trie[fail[cur]].son[i];
q.push(trie[cur].son[i]);
} else {
trie[cur].son[i] = trie[fail[cur]].son[i];
}
}
}
}
void query(char *s) {
int len = strlen(s);
int cur = 0;
for (int i = 0; i < len; i++) {
int c = s[i] - 'A';
if (c < 0 || c > 25) {
cur = 0;
continue;
}
cur = trie[cur].son[c];
int j = cur;
while (j) {
if (trie[j].id) {
ans[trie[j].id]++;
}
j = fail[j];
}
}
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int n;
while (cin >> n) {
cnt = 0;
trie[0].init();
memset(ans, 0, sizeof(ans));
memset(fail, 0, sizeof(fail));
for (int i = 1; i <= n; i++) {
scanf("%s", virus[i]);
insert(virus[i], i);
}
getfail();
scanf("%s", str);
query(str);
for (int i = 1; i <= n; i++) {
if (ans[i]) {
printf("%s: %d\n", virus[i], ans[i]);
}
}
}
return 0;
}