ac自动机含义:tire+KMp;
A. 【例题1】单词查询:
本题主要是查询,可以建立一个cnt数组,和tire树中含义一样,最后定义一个ans,将ans加上查询到的cnt,输出ans就行了。
code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 1e4 + 10, M = 1e6 + 10;
int ch[M][30], n, idx = 0, cnt[M], ne[M], ans, heap[M];
char str[M];
inline void insert(char str[]) {
int p = 1, n = strlen(str + 1);
for (int i = 1; i <= n; i++) {
int u = str[i] - 'a';
if (!ch[p][u]) {
ch[p][u] = ++idx;
memset(ch[idx], 0, sizeof ch[idx]);
}
p = ch[p][u];
}
cnt[p]++;
return;
}
inline void build() {
for (int i = 0; i < 26; i++) {
ch[0][i] = 1;
}
heap[1] = 1, ne[1] = 0;
for (int q1 = 1, q2 = 1; q1 <= q2; q1++) {
int u = heap[q1];
for (int i = 0; i < 26; i++) {
if (!ch[u][i])
ch[u][i] = ch[ne[u]][i];//路径压缩,在寻找ne中减少迭代次数
else {
heap[++q2] = ch[u][i];//bfs();
ne[ch[u][i]] = ch[ne[u]][i];//向后寻找ne
}
}
}
return;
}
inline void find(char str[]) {
int p = 1, len = strlen(str + 1);
for (int i = 1; i <= len; i++) {
int u = str[i] - 'a';
int k = ch[p][u];
while (k > 1) {
ans += cnt[k];//遍历每一个cnt,找到匹配的前缀
cnt[k] = 0;
k = ne[k];
}
p = ch[p][u];
}
return;
}
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
ans = 0, idx = 1;
memset(cnt, 0, sizeof cnt);
memset(heap, 0, sizeof heap);
for (int i = 0; i < 26; i++) ch[0][i] = 1, ch[1][i] = 0;//初始化
for (int i = 1; i <= n; i++) {
scanf("%s", str + 1);
insert(str);//tire树中的插入
}
build();
scanf("%s", str + 1);
find(str + 1);
cout << ans << endl;
}
return 0;
}
B. 【例题2】单词频率:
本题主要是查询出现次数,可以建立一个sum数组,最后通过ne对其求一遍前缀和就可以了,同时也要使用cnt来存储编号(ne要走到底),code:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int M = 1e6 + 10;
char str[M];
int ch[M][30], ne[M], que[M], sum[M], sum1[M], pos[M], idx = 1, ans = 0, n, tot;
inline void insert(char str[]) {
int p = 1, len = strlen(str);
for (int i = 0; i < len; i++) {
int u = str[i] - 'a';
if (!ch[p][u])
ch[p][u] = ++idx;
p = ch[p][u];
sum[p]++;
}
pos[++tot] = p;
return;
}
inline void bfs() {
for (int i = 0; i < 26; i++) ch[0][i] = 1;
que[1] = 1, ne[1] = 0;
for (int q1 = 1, q2 = 1; q1 <= q2; q1++) {
int u = que[q1];
for (int i = 0; i < 26; i++) {
if (!ch[u][i])
ch[u][i] = ch[ne[u]][i];
else {
que[++q2] = ch[u][i];
ne[ch[u][i]] = ch[ne[u]][i];
}
}
}
for (int i = idx; i >= 0; i--) {
sum1[que[i]] = sum[que[i]];
}
for (int i = idx; i >= 0; i--) {
sum1[ne[que[i]]] += sum1[que[i]];
}
}
int main() {
cin >> n;
idx = 1;
for (int i = 1; i <= n; i++) {
scanf("%s", str);
insert(str);
}
bfs();
for (int i = 1; i <= n; i++) {
cout << sum1[pos[i]] << endl;
}
return 0;
}
如有疑问可以来私信问我,本人会在第一时间内回复