题目大意:多组询问的AC自动机
这里注意一下在HDU2222的基础上修改一下不要把FLAG清零,同时用一个数组记录一下那些出现过就行了
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
#define rep(i,k) for(int (i)=1;(i)<=(k);(i)++)
const int MAXN = 500;
struct State{
int fail, flag;
int ch[128];
}p[MAXN*200+30];
int scnt, Bef[MAXN*200+30];
void Add(char *s, int id){
int now = 0, len = strlen(s);
for(int i=0;i<len;i++){
if(!p[now].ch[s[i]]){
p[now].ch[s[i]] = ++scnt;
now = scnt;
}else now = p[now].ch[s[i]];
}
p[now].flag = id;
}
void _initTree(){
queue<int> que;
for(int i=0;i<128;i++)
if(p[0].ch[i])
que.push(p[0].ch[i]);
while(!que.empty()){
int u = que.front();
que.pop();
for(int i=0;i<128;i++) if(p[u].ch[i]){
int v = p[u].ch[i];
que.push(v);
int k = p[u].fail;
while(k && !p[k].ch[i]) k = p[k].fail;
p[v].fail = p[k].ch[i];
Bef[v] = p[p[v].fail].flag > 0 ? p[v].fail : Bef[p[v].fail];
}
}
}
char ls[10010];
bool ans[MAXN+20];
int match(int id){
int len = strlen(ls);
int u = 0, counter = 0;
memset(ans, 0, sizeof ans);
for(int i=0;i<len;i++){
if(p[u].ch[ls[i]])
u = p[u].ch[ls[i]];
else{
int k = p[u].fail;
while(k && !p[k].ch[ls[i]]) k = p[k].fail;
u = p[k].ch[ls[i]];
}
int k = u;
while(k){
if(p[k].flag){
ans[p[k].flag] = 1;
counter=1;
}
k = Bef[k];
}
}
if(!counter) return 0;
printf("web %d:", id);
for(int i=1;i<=MAXN;i++)
if(ans[i])
printf(" %d", i);
printf("\n");
return 1;
}
int main(){
char s[300];
int T, n;
scanf("%d", &T);
for(int i=1;i<=T;i++){
scanf("%s", s);
Add(s, i);
}
_initTree();
int tot = 0;
scanf("%d", &n);
rep(num, n){
scanf("%s", ls);
tot += match(num);
}
printf("total: %d\n", tot);
return 0;
}