HDU2896 病毒侵袭

来源:互联网 发布:16总决赛骑士数据 编辑:程序博客网 时间:2024/06/06 02:39

题目传送门

AC自动机第一题~

一看就是一个非常简单的多串匹配问题了,输出方案?记录一下就好了

注意这里code是Trie图,它是AC自动机的改进版本,有效利用了原本无用的边,这反而简化了代码

#include<queue>#include<stdio.h>#include<string.h>#include<algorithm>#define N 100010using namespace std;char s[N];int fail[N],son[N][128],c[N],cnt=1,n,T=0;inline void insert(char* s,int pos){    int x=1;    for(;*s;++s)        x=son[x][*s]?son[x][*s]:son[x][*s]=++cnt;    c[x]=pos;}inline void build(){    queue<int> q;    for(int i=0;i<128;++i)        if(!son[1][i]) son[1][i]=1;        else q.push(son[1][i]),fail[son[1][i]]=1;    for(int x;!q.empty();q.pop()){        x=q.front();        for(int i=0;i<128;++i)            if(!son[x][i]) son[x][i]=son[fail[x]][i];        else q.push(son[x][i]),fail[son[x][i]]=son[fail[x]][i];    }}inline bool query(char* s){    bool vis[510]={0},v=0;    for(int x=1;*s;++s){        x=son[x][*s];        for(int j=x;j!=1;j=fail[j])            if(c[j]) vis[c[j]]=v=1;    }    if(!v) return 0;    printf("web %d:",T);    for(int i=1;i<=n;++i)         if(vis[i]) printf(" %d",i);    puts(""); return 1;}int __18520(){    if(scanf("%d",&n)<0) return 0;     for(int i=1;i<=n;++i){        scanf("%s",s); insert(s,i);    }    build(); int ans=0,m; scanf("%d",&m);     for(T=1;T<=m;++T){        scanf("%s",s); ans+=query(s);    }    printf("total: %d\n",ans); return cnt=1;}int main(){ while(__18520()); }

原创粉丝点击