题目大意:给出若干病毒的特征码,不超过500个。每个病毒的特征码长度在20~200之间。现在有若干网站的源代码,要检测网站的源代码中是否包含病毒。网站的个数不超过1000个,每个网站的源代码长度在7000~10000之间。已知如果包含病毒,最多包含三个病毒。输出每个含病毒网站包含的病毒的编号等信息,最后输出含病毒网站的个数。
裸的AC自动机题目。一开始把病毒的个数弄错了。因为宏定义比较多,一开始没有弄#define,全弄的数字。后边发现数字错了。改了一下,又改漏了一个。后边看别人的discuss,说是什么连续不重复匹配。结果完全是误导人。就是一个普通的字符串匹配。以后还是用宏来定义数组长度吧
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define MAXC 130 struct node { int id,fail,nxt[MAXC]; }trie[100010]; char word[202],web[10005]; int head,tail,tot=1,root=1,myq[100010],ans[502],bdk,n,m,bdwebs=0,res[10]; void insert(int r,char *s,int id) { int len=strlen(s); for(int i=0;i<len;i++) { if(trie[r].nxt[s[i]-32]==0) trie[r].nxt[s[i]-32]=++tot; r=trie[r].nxt[s[i]-32]; } trie[r].id=id; } void build(int r) { trie[r].fail=r; myq[tail++]=r; while(head<tail) { r=myq[head++]; for(int i=0;i<MAXC;i++) { int ch=trie[r].nxt[i],failp; if(ch) { myq[tail++]=ch; for(failp=trie[r].fail;failp!=root&&trie[failp].nxt[i]==0;failp=trie[failp].fail); if(trie[failp].nxt[i]==0||trie[failp].nxt[i]==ch) trie[ch].fail=failp; else trie[ch].fail=trie[failp].nxt[i]; } } } } void query(int r,char *s) { int len=strlen(s),tempfail; for(int i=0;i<len;i++) { while(trie[r].nxt[s[i]-32]==0&&r!=root) r=trie[r].fail; r=trie[r].nxt[s[i]-32]; if(r==0)r=root; for(tempfail=r;tempfail!=root;tempfail=trie[tempfail].fail) { if(ans[trie[tempfail].id])break; if(trie[tempfail].id>0) {ans[trie[tempfail].id]=1; } } } } int main() { root=1; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%s",word); insert(root,word,i+1); } build(root); scanf("%d",&m); for(int i=0;i<m;i++) { scanf("%s",web); memset(ans,0,sizeof ans); bdk=0; query(root,web); for(int k=0;k<502;k++) if(ans[k])res[bdk++]=k; if(bdk>0) { bdwebs++; printf("web %d:",i+1); for(int k=0;k<bdk;k++) printf(" %d",res[k]); printf(" "); } } printf("total: %d ",bdwebs); return 0; }