题意:对于每一个网站找出含有的所有的病毒串,最后输出含有病毒串的网站个数.
把每个病毒串加入到自动机里,然后每次判断一个网站的时候遍历一次,为了去重开一个数组标记下就好了.
坑点:1.字符个数有点多,我开128爆内存了,实际上前面ASCLL码前20个是不需要的;2.注意病毒有重复的.
#include <bits/stdc++.h>
using namespace std;
#define maxn 100005
#define maxm 11111
int n, m;
struct trie {
int next[maxn][110], fail[maxn], end[maxn];
int root, cnt;
vector <int> f[maxn];
int new_node () {
memset (next[cnt], -1, sizeof next[cnt]);
end[cnt++] = 0;
return cnt-1;
}
void init () {
cnt = 0;
root = new_node ();
for (int i = 0; i < maxn; i++) f[i].clear ();
}
void insert (char *buf, int pos) {
int len = strlen (buf);
int now = root;
for (int i = 0; i < len; i++) {
int id = buf[i]-20;
if (next[now][id] == -1) {
next[now][id] = new_node ();
}
now = next[now][id];
}
end[now]++;
f[now].push_back (pos);
}
void build () {
queue <int> q;
fail[root] = root;
for (int i = 0; i < 110; i++) {
if (next[root][i] == -1) {
next[root][i] = root;
}
else {
fail[next[root][i]] = root;
q.push (next[root][i]);
}
}
while (!q.empty ()) {
int now = q.front (); q.pop ();
for (int i = 0; i < 110; i++) {
if (next[now][i] == -1) {
next[now][i] = next[fail[now]][i];
}
else {
fail[next[now][i]] = next[fail[now]][i];
q.push (next[now][i]);
}
}
}
}
bool vis[maxn];
int query (char *buf, int kase) {
int len = strlen (buf);
int now = root;
vector <int> ans;
ans.clear ();
memset (vis, 0, sizeof vis);
for (int i = 0; i < len; i++) {
int id = buf[i]-20;
now = next[now][id];
int tmp = now;
while (tmp != root) {
if (end[tmp] && !vis[tmp]) {
for (int j = 0; j < f[tmp].size (); j++) {
ans.push_back (f[tmp][j]);
}
}
vis[tmp] = 1;
tmp = fail[tmp];
}
}
if (ans.size ()) {
sort (ans.begin (), ans.end ());
printf ("web %d: ", kase);
int Max = ans.size ();
printf ("%d", ans[0]);
for (int i = 1; i < Max; i++) {
printf (" %d", ans[i]);
}
printf ("\n");
return 1;
}
return 0;
}
}ac;
char a[maxm];
int main () {
while (scanf ("%d", &n) == 1) {
ac.init ();
for (int i = 1; i <= n; i++) {
scanf ("%s", a);
ac.insert (a, i);
}
ac.build ();
scanf ("%d", &m);
int ans = 0;
for (int i = 1; i <= m; i++) {
scanf ("%s", a);
if (ac.query (a, i))
ans++;
}
printf ("total: %d\n", ans);
}
return 0;
}