史上最裸 AC 自动机 第二弹
来源:互联网 发布:海淘转运系统源码 编辑:程序博客网 时间:2024/06/05 18:51
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cstdlib>#include<queue>#include<set>using namespace std;const int maxn=512;int n,m,ans,res,que[maxn];struct node{ int idx,flag; node *fail; node *next[100]; node() { memset(next,0,sizeof(next)); idx=0; flag=0; fail=NULL; }};void Insert(node *rt,char s[],int idx){ node *p=rt; int i=0; while(s[i]) { int k=s[i++]-32; if(p->next[k]==NULL)p->next[k]=new node(); p=p->next[k]; } p->flag=1;//字符串结尾 p->idx=idx;//代表第几个字符串}void build_AC(node *rt){ int i,j=0; queue<node*>q; rt->fail=NULL; q.push(rt); while(!q.empty()) { node *p=q.front(); q.pop(); for(i=0;i<100;i++) { if(p->next[i]!=NULL)//寻找当前子树的失败指针 { if(p==rt) { p->next[i]->fail=rt; }else { node *tmp=p->fail; while(tmp!=NULL) { if(tmp->next[i]!=NULL)//找到失败指针 { p->next[i]->fail=tmp->next[i]; // if(tmp->next[i]->flag==1) p->next[i]->flag=1; break; } tmp=tmp->fail; } if(tmp==NULL)p->next[i]->fail=rt;//无法获取,当前子树的失败指针为根 } q.push(p->next[i]); } } }}void query_AC(node *rt,char s[]){ int i=0,j; node *p=rt; while(s[i]) { int k=s[i++]-32; while(p->next[k]==NULL&&p!=rt)p=p->fail;//失配 p=p->next[k]; if(p==NULL)p=rt;//失配指针为根 node *tmp=p; while(tmp!=rt)//&&!vis[tmp->idx] { if(tmp->idx) que[ans++]=tmp->idx; tmp=tmp->fail; } }}int main(){ char s[12020]; char ss[210]; while(scanf("%d",&n)!=EOF) { int i,j; ans=res=0; node *rt=new node(); for(i=1;i<=n;i++) { scanf("%s",ss); Insert(rt,ss,i); } build_AC(rt); scanf("%d",&m); for(ans=0,i=1;i<=m;i++) { scanf("%s",s); query_AC(rt,s); if(ans) { res++; printf("web %d:",i); sort(que,que+ans); int cnt=unique(que,que+ans)-que; for(j=0;j<cnt;j++) cout<<" "<<que[j]; cout<<endl; } ans=0; } printf("total: %d\n",res); } return 0;}