HDU2896 病毒的侵扰
http://vjudge.net/problem/viewProblem.action?id=16404
题目大意:
记录每个病毒的编号,并给出一些网站的源码,分别输出网站及其对应编号中所含病毒的编号,没有就不输出
最后输出有病毒网站的个数
这道题需要注意的是这个所有ASCII码均会用到,所以我之前傻傻地写str[i]-'a'还不知为什么会错简直苦逼~~
这里直接用ch[now][str[i]]找到对应位置即可
因为要记录编号,为了防止重复访问,我对query中进行了一个visit[]数组访问进行判断的操作
query函数如下:
1 void query(char *str){ 2 int len=strlen(str); 3 int now=root,ret=0; 4 for(int i=0;i<len;i++){ 5 now=ch[now][str[i]]; 6 int k=now; 7 while(k!=root&&(!visit[k]&&val[k])){//这是要循环到找到fail值为root的时候或者找到匹配的字符串的时候,否则一直向前找fail值, 8 if(!visit[k])sum++,ans[ret++]=val[k],visit[k]=1; 9 k=last[k]; 10 } 11 } 12 }
用ans[]记录所有编号,sum记录病毒个数,那么就可以在main函数进行sort(ans,ans+sum)进行排序好就可以输出了
总代码如下:
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 using namespace std; 6 #define N 500*201 7 char str[10005]; 8 int ans[505],visit[N],sum; 9 struct AC{ 10 int ch[N][128],fail[N],val[N],last[N],tmp,root,cnt; 11 int newnode(){ 12 val[tmp]=0; 13 memset(ch[tmp],0,sizeof(ch[tmp])); 14 return tmp++; 15 } 16 void init(){ 17 tmp=0,cnt=0; 18 root=newnode(); 19 } 20 void add(char *s){ 21 int len=strlen(s); 22 int now=root; 23 for(int i=0;i<len;i++){ 24 int &k=ch[now][s[i]]; 25 if(!k) k=newnode(); 26 now=k; 27 } 28 cnt++; 29 val[now]=cnt; 30 } 31 void get_fail(){ 32 fail[root]=root; 33 queue<int> q; 34 for(int i=0;i<128;i++){ 35 int v=ch[root][i]; 36 if(v) 37 fail[v]=last[v]=0,q.push(v); 38 } 39 while(!q.empty()){ 40 int now=q.front(); 41 q.pop(); 42 for(int i=0;i<128;i++){ 43 int v=ch[now][i]; 44 if(!v) ch[now][i]=ch[fail[now]][i]; 45 else{ 46 fail[v]=ch[fail[now]][i]; 47 last[v]=val[fail[v]]?fail[v]:last[fail[v]]; 48 q.push(v); 49 } 50 } 51 } 52 } 53 void query(char *str){ 54 int len=strlen(str); 55 int now=root,ret=0; 56 for(int i=0;i<len;i++){ 57 now=ch[now][str[i]]; 58 int k=now; 59 while(k!=root&&(!visit[k]&&val[k])){//这是要循环到找到fail值为root的时候或者找到匹配的字符串的时候,否则一直向前找fail值, 60 if(!visit[k])sum++,ans[ret++]=val[k],visit[k]=1; 61 k=last[k]; 62 } 63 } 64 } 65 }ac; 66 int main() 67 { 68 int n,m; 69 while(scanf("%d",&n)!=EOF){ 70 memset(ans,0,sizeof(ans)); 71 ac.init(); 72 for(int i=0;i<n;i++){ 73 scanf("%s",str); 74 ac.add(str); 75 } 76 ac.get_fail(); 77 scanf("%d",&m); 78 int c=0; 79 for(int i=1;i<=m;i++){ 80 sum=0; 81 scanf("%s",str); 82 memset(visit,0,sizeof(visit)); 83 ac.query(str); 84 sort(ans,ans+sum); 85 if(sum>0){ 86 printf("web %d:",i); 87 for(int j=0;j<sum;j++) printf(" %d",ans[j]); 88 printf("\n"); 89 c++; 90 } 91 } 92 printf("total: %d\n",c); 93 } 94 return 0; 95 }