题意
传送门 HDU 2896
题解
A C AC AC 自动机的节点记录特征码的编号,查询时统计即可,注意字符集为 ASCⅡ。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define maxn 505
#define base 128
#define maxl 10005
int n, m, ns, ms, trie[maxn * 200][base], id[maxn * 200], fail[maxn * 200];
bool vis1[maxn * 200], vis2[maxn];
char str[maxl];
void insert(char *s, int k)
{
int len = strlen(s), p = 0;
for (int i = 0; i < len; i++)
{
int c = s[i];
if (!trie[p][c])
{
trie[p][c] = ++ns;
}
p = trie[p][c];
}
id[p] = k;
}
void getFail()
{
queue<int> q;
for (int i = 0; i < base; i++)
{
if (trie[0][i])
{
fail[trie[0][i]] = 0;
q.push(trie[0][i]);
}
}
while (!q.empty())
{
int p = q.front();
q.pop();
for (int i = 0; i < base; i++)
{
if (trie[p][i])
{
fail[trie[p][i]] = trie[fail[p]][i];
q.push(trie[p][i]);
}
else
{
trie[p][i] = trie[fail[p]][i];
}
}
}
}
void query(char *s, int k)
{
memset(vis1, 0, sizeof(bool) * 200 * n);
memset(vis2, 0, sizeof(bool) * n);
int len = strlen(s), p = 0;
bool f = 0;
for (int i = 0; i < len; i++)
{
int c = s[i];
p = trie[p][c];
for (int j = p; j && !vis1[j]; j = fail[j])
{
if (id[j])
{
vis2[id[j]] = 1, f = 1;
}
vis1[j] = 1;
}
}
if (f)
{
++ms;
printf("web %d:", k);
for (int i = 1; i <= n; i++)
{
if (vis2[i])
{
printf(" %d", i);
}
}
putchar('\n');
}
}
int main()
{
scanf("%d", &n);
getchar();
char s[205];
ns = ms = 0;
for (int i = 1; i <= n; i++)
{
gets(s);
insert(s, i);
}
getFail();
scanf("%d", &m);
getchar();
for (int i = 1; i <= m; i++)
{
gets(str);
query(str, i);
}
printf("total: %d\n", ms);
return 0;
}