ac自动机模板

╄→尐↘猪︶ㄣ 提交于 2019-11-27 05:09:10

易理解版本:
// 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));
}
}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!