题意:给出n个模式串,然后m个目标串,问每个目标串里用了哪些模式串,一共有多少个目标串内存在模式串。
题解:如果当前字符是某个模式串的结尾字符,val[u]存模式串的编号,也算是个模板题。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 100005;
const int SIGMA_SIZE = 128;
int Next[N][SIGMA_SIZE], fail[N], val[N], sz, n, m;
char str[N];
void insert(char *s, int v) {
int u = 0, len = strlen(s);
for (int i = 0; i < len; i++) {
if (!Next[u][s[i]]) {
memset(Next[sz], 0, sizeof(Next[sz]));
val[sz] = 0;
Next[u][s[i]] = sz++;
}
u = Next[u][s[i]];
}
val[u] = v;
}
void getFail() {
queue<int> q;
fail[0] = 0;
for (int i = 0; i < SIGMA_SIZE; i++) {
if (Next[0][i]) {
fail[Next[0][i]] = 0;
q.push(Next[0][i]);
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = 0; i < SIGMA_SIZE; i++) {
if (!Next[u][i])
Next[u][i] = Next[fail[u]][i];
else {
fail[Next[u][i]] = Next[fail[u]][i];
q.push(Next[u][i]);
}
}
}
}
bool query(char *s, int id) {
int len = strlen(s), u = 0, flag[505];
memset(flag, 0, sizeof(flag));
int flag2 = 0;
for (int i = 0; i < len; i++) {
u = Next[u][s[i]];
int temp = u;
while (temp != 0) {
if (val[temp]) {
flag[val[temp]] = 1;
flag2 = 1;
}
temp = fail[temp];
}
}
if (!flag2) return false;
printf("web %d:", id);
for (int i = 1; i <= n; i++)
if (flag[i])
printf(" %d", i);
printf("\n");
return true;
}
int main() {
while (scanf("%d", &n) == 1) {
sz = 1;
memset(Next[0], 0, sizeof(Next[0]));
for (int i = 0; i < n; i++) {
scanf("%s", str);
insert(str, i + 1);
}
getFail();
scanf("%d", &m);
int tot = 0;
for (int i = 0; i < m; i++) {
scanf("%s", str);
if (query(str, i + 1))
tot++;
}
printf("total: %d\n", tot);
}
return 0;
}
本文介绍了一种使用AC自动机进行模式串匹配的方法。该方法可以高效地处理多个模式串,并在一个目标串中查找这些模式串出现的位置。通过构建自动机并利用失败指针加速匹配过程,适用于大规模文本搜索应用。
1469

被折叠的 条评论
为什么被折叠?



