史上最裸 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;}