题意:
给出n个病毒串,然后给出m个网站的串,问每个网站中有哪些 病毒出现并输出,最后统计有有病毒的网站数量。
题解:
ac自动机,end记录某个病毒的编号。突发奇想用set去存每个网站的病毒,这样既可以去重有可以递增输出,而且set绝对比自己手写的方法快毕竟logn的复杂度。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<map> #include<set> using namespace std; #define B(x) (1<<(x)) typedef long long ll; const int oo=0x3f3f3f3f; const ll OO=1LL<<61; const ll MOD=10007; const int maxn=10005; const int SIZE=210*500; char str[maxn]; set<int>ans; struct AC { int next[SIZE][128],fail[SIZE],end[SIZE],Q[SIZE*128]; int root,cnt; void Init() { cnt=0; root=newNode(); } int newNode() { for(int i=0;i<128;i++) next[cnt][i]=-1; end[cnt++]=0; return cnt-1; } void Insert(char buff[],int id) { int now=root; int len=strlen(buff); for(int i=0,k;i<len;i++) { k=buff[i]; if(next[now][k]==-1) next[now][k]=newNode(); now=next[now][k]; } end[now]=id;///记录编号 } void build() { fail[root]=root; int front,rear; front=rear=0; int now=root; for(int i=0;i<128;i++) { if(next[now][i]==-1) next[now][i]=root; else { fail[next[now][i]]=root; Q[rear++]=next[now][i]; } } while(front<rear) { now=Q[front++]; for(int i=0;i<128;i++) { if(next[now][i]==-1) next[now][i]=next[fail[now]][i]; else { fail[next[now][i]]=next[fail[now]][i]; Q[rear++]=next[now][i]; } } } } int Search(char buff[]) { int now=root,f=0; int len=strlen(buff); for(int i=0;i<len;i++) { now=next[now][buff[i]]; int temp=now; while(temp!=root) { if(end[temp]) { f=1; ans.insert(end[temp]); } temp=fail[temp]; } } return f; } void Debug() { for(int i=0;i<cnt;i++) { printf("id=%3d fail=%3d end=%3d child=[",i,fail[i],end[i]); for(int j=0;j<26;j++) printf(" %3d",next[i][j]); printf(" ]\n"); } } }; AC ac; int main() { int n,m,cnt; while(scanf("%d",&n)!=EOF) { cnt=0; ac.Init(); for(int i=1;i<=n;i++) { scanf("%s",str); ac.Insert(str,i); } ac.build(); scanf("%d",&m); for(int i=1;i<=m;i++) { ans.clear(); scanf("%s",str); if(ac.Search(str)) { cnt++; printf("web %d:",i); for(set<int>::iterator it=ans.begin();it!=ans.end();++it) printf(" %d",*it); puts(""); } } printf("total: %d\n",cnt); } return 0; }