题意:
给n个模式串和m个文本串,问有几个文本串包含任意一个模式串,并且输出每个包含任意模式串的文本串,包含的是哪几个模式串。
做法:
ac自动机模板。
整天模板题做做还有什么希望(大雾)模板居然调了一个小时
代码:
/*************************************************************
Problem: hdu 2896 病毒侵袭
User: fengyuan07
Language: C++
Result: Accepted
Time: 265MS
Memory: 31364K
Submit_Time: 2018-01-12 00:09:08
*************************************************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cctype>
#include<queue>
using namespace std;
const int N = 110000, M = 130;
int n, m, tot, all, cas, sum;
int c[N][M], w[N], fail[N], vis[N], ans[N];
char s[N];
inline void insert(char s[], int id)
{
int len = strlen(s), o = 0;
for(int i = 0; i < len; i ++) {
if(!c[o][s[i]]) c[o][s[i]] = ++ tot;
o = c[o][s[i]];
}
w[o] = id;
}
inline void build()
{
queue<int> q;
for(int i = 0; i <= 128; i ++) { if(c[0][i]) q.push(c[0][i]); fail[c[0][i]] = 0; }
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = 0; i <= 128; i ++) if(c[u][i]) {
fail[c[u][i]] = c[fail[u]][i];
q.push(c[u][i]);
} else c[u][i] = c[fail[u]][i];
}
}
inline void query(char s[])
{
int len = strlen(s), o = 0;
for(int i = 0; i < len; i ++) {
o = c[o][s[i]];
for(int j = o; j && !vis[j]; j = fail[j]) {
if(w[j]) ans[++ sum] = w[j];
vis[j] = 1;
}
}
}
int main()
{
scanf("%d", &n); getchar();
for(int i = 1; i <= n; i ++) {
gets(s);
insert(s, i);
}
build();
scanf("%d", &m); getchar();
for(int i = 1; i <= m; i ++) {
memset(vis, 0, sizeof vis); sum = 0;
gets(s);
query(s);
if(sum > 0) {
all ++;
printf("web %d:", i); sort(ans+1, ans+1+sum);
for(int j = 1; j <= sum; j ++) printf(" %d", ans[j]);
puts("");
}
}
printf("total: %d\n", all);
return 0;
}