易理解版本:
// http://acm.hdu.edu.cn/showproblem.php?pid=2222
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
struct Tri {
int ch[maxn][26], val[maxn], fail[maxn], sz;
void init() {
memset(ch[0], 0, sizeof(ch[0]));
sz = 0;
}
void insert(char *s) {
int o = 0;
for (int i = 0; s[i]; i++) {
int c = s[i] - ‘a’;
if (!ch[o][c]) { //建立新节点
ch[o][c] = ++sz;
val[sz] = 0;
memset(ch[sz], 0, sizeof(ch[sz]));
}
o = ch[o][c];
}
val[o]++;
}
void build() {
queue q;
for (int i = 0; i < 26; i++)
if (ch[0][i]) {
q.push(ch[0][i]);
fail[ch[0][i]] = 0;//第一层节点fail都指向根
}
while (!q.empty()) {
int o = q.front();
q.pop();
for (int i = 0; i < 26; i++)
if (ch[o][i]) {
int v = ch[o][i];
int fa = fail[o];
while (fa && !ch[fa][i])//如果当前节点没有 i 号儿子,继续跳fail指针,直到根或者有 i 号节点
fa = fail[fa];
fail[v] = ch[fa][i];
q.push(v);
}
}
}
int query(char *s) {
int o = 0, ans = 0;
for (int i = 0; s[i]; i++) {
int c = s[i] - ‘a’;
while (!ch[o][c] && o)
o = fail[o];
o = ch[o][c];
int tmp = o;
while (tmp) { //每次不仅要记录当前节点的答案,也要记录失败指针指向的节点的答案
ans += val[tmp];
val[tmp] = 0;
tmp = fail[tmp];
}
}
return ans;
}
} ac;
char s[maxn];
int main() {
int T;
scanf("%d", &T);
while (T–) {
int n;
ac.init();
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%s", s);
ac.insert(s);
}
ac.build();
scanf("%s", s);
printf("%d\n", ac.query(s));
}
}
//精简版本
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
struct Tri {
int ch[maxn][26], val[maxn], fail[maxn], sz;
void init() {
memset(ch[0], 0, sizeof(ch[0]));
sz = 0;
}
void insert(char *s) {
int o = 0;
for (int i = 0; s[i]; i++) {
int c = s[i] - ‘a’;
if (!ch[o][c]) {
ch[o][c] = ++sz;
val[sz] = 0;
memset(ch[sz], 0, sizeof(ch[sz]));
}
o = ch[o][c];
}
val[o]++;
}
void build() {
queue q;
for (int i = 0; i < 26; i++)
if (ch[0][i]) {
q.push(ch[0][i]);
fail[ch[0][i]] = 0;
}
while (!q.empty()) {
int o = q.front();
q.pop();
for (int i = 0; i < 26; i++)
if (ch[o][i]) {
int v = ch[o][i];
fail[v] = ch[fail[o]][i];
q.push(v);
}
else
ch[o][i] = ch[fail[o]][i];
}
}
int query(char *s) {
int o = 0, ans = 0;
for (int i = 0; s[i]; i++) {
int c = s[i] - ‘a’;
o = ch[o][c];
int tmp = o;
while (tmp) {
ans += val[tmp];
val[tmp] = 0;
tmp = fail[tmp];
}
}
return ans;
}
} ac;
char s[maxn];
int main() {
int T;
scanf("%d", &T);
while (T–) {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%s", s);
ac.insert(s);
}
ac.build();
scanf("%s", s);
printf("%d\n", ac.query(s));
}
}
ac自动机模板
最新推荐文章于 2024-06-04 08:36:20 发布