[hdu2896]病毒侵袭(AC自动机)
题意:给出n个病毒和m个网站,找出每一个网站中含有的病毒种类,并按病毒编号升序输出,最后统计含有病毒的网站个数。
每道AC自动机不同的地方就是end数组代表的意义,这里还需要加一个vis数组判断是否访问过。其他就是ASCII码可见字符为32-196 共95个字符。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=96; 5 const int MAXN=100010; 6 int num,ans[5],nn; 7 bool vis[MAXN]; 8 struct Trie{//数组形式 9 int Next[MAXN][N],Fail[MAXN],End[MAXN],root,tot;//大小为所以匹配字符串的总和 10 int newnode(){//结构体内部用 11 for(int i=0;i<N;i++) Next[tot][i]=-1; 12 End[tot++]=0; 13 return tot-1; 14 } 15 void init(){ 16 tot=0; 17 root=newnode(); 18 } 19 void insert(char buf[],int x){ 20 int len=strlen(buf); 21 int now=root;//now是temp指针 22 for(int i=0;i<len;i++){ 23 int k=buf[i]-32; 24 if(Next[now][k]==-1) Next[now][k]=newnode();//next数组代表的是下一个字符索引 25 now=Next[now][k]; 26 } 27 End[now]=x;//end数组是当前字符串的个数.字典中可能有相同的单词,若只算一次,改为1. 28 } 29 void build(){//构造fail指针,后缀是某些前缀 30 queue<int>que; 31 Fail[root]=root; 32 for(int i=0;i<N;i++){ 33 if(Next[root][i]==-1) Next[root][i]=root; 34 else{ 35 Fail[Next[root][i]]=root; 36 que.push(Next[root][i]); 37 } 38 } 39 while(!que.empty()){//bfs,会将所有的匹配子串都遍历到 40 int now=que.front(); 41 que.pop(); 42 for(int i=0;i<N;i++){ 43 if(Next[now][i]==-1) Next[now][i]=Next[Fail[now]][i]; 44 else{ 45 Fail[Next[now][i]]=Next[Fail[now]][i];//fail指向最长的 46 que.push(Next[now][i]); 47 } 48 } 49 } 50 } 51 void query(char buf[]){ 52 int len=strlen(buf),now=root; 53 for(int i=0;i<len;i++){ 54 now=Next[now][buf[i]-32]; 55 int temp=now; 56 while(temp!=root){ 57 if(!vis[temp]&&End[temp]) ans[nn++]=End[temp]; 58 vis[temp]=true; 59 temp=Fail[temp]; 60 } 61 } 62 } 63 }; 64 65 Trie ac; 66 char buf[10003]; 67 int n,m; 68 int main(){ 69 num=0; 70 ios::sync_with_stdio(0); 71 ac.init(); 72 cin>>n; 73 for(int i=1;i<=n;i++){ 74 cin>>buf; 75 ac.insert(buf,i); 76 } 77 ac.build();//不要忘记build 78 cin>>m; 79 for(int i=1;i<=m;i++){ 80 memset(vis,0,sizeof vis); 81 nn=0; 82 cin>>buf; 83 ac.query(buf); 84 if(nn==0) continue; 85 sort(ans,ans+nn); 86 cout<<"web "<<i<<":"; 87 for(int j=0;j<nn;j++){ 88 cout<<" "<<ans[j]; 89 } 90 cout<<"\n"; 91 num++; 92 } 93 cout<<"total: "<<num<<"\n"; 94 return 0; 95 }