题意:
给出一个病毒库,然后给出一个网站,求这个病毒库中的病毒在这个网站上出现的次数。
题解:
直接ac自动机,然后用set保存出现在这个网站上的病毒编号。
#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=2000000+5; const int SIZE=1000*55; char str[1005][55]; char buff[maxn]; int ans[1005]; set<int>StrId; 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]; } } } } void Search(char buff[]) { int now=root; 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]) StrId.insert(end[temp]); ans[end[temp]]++; temp=fail[temp]; } } } 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) { memset(ans,0,sizeof ans); StrId.clear(); ac.Init(); for(int i=1;i<=n;i++) { scanf("%s",str[i]); ac.Insert(str[i],i); } ac.build(); scanf("%s",buff); ac.Search(buff); for(set<int>::iterator it=StrId.begin();it!=StrId.end();++it) printf("%s: %d\n",str[*it],ans[*it]); } return 0; }