hdu 2896 病毒侵袭 (AC自动机)


题目大意:给你一堆病毒串,再给你一些网站,问每个网站是否包含病毒串,若包括,包括哪几个病毒串,还有一共有几个网站包含病毒串。


啊啊,自己第一道AC自动机的题,还是比较简单的模板题吧,过几天要总结一下AC自动机呀。

思路很简单了,将所有病毒串构成trie树,然后求AC自动机,再用每个网站在AC自动机上跑就行了。跑的时候开一个数组记录每个网站包含的病毒串。每经过一个节点由失败指针向上移,看是否有病毒串(即flag为1的节点)。应该还可以优化的,不过数据量不大,跑的还是挺快的,呵呵。

过几天研究下AC自动机的数组实现,还有结合DP还有矩阵的题。到时候发个总结吧

挫代码如下:


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#define maxn 100100
#define knum 94
using namespace std;
struct trie
{
    int flag;
    trie *fail;
    trie *go[knum];
}node[maxn],*root;
int tot;
trie * newnode()
{
    memset(node[tot].go,NULL,sizeof(node[tot].go));
    node[tot].fail=NULL;
    node[tot].flag=0;
    return &node[tot++];
}
queue <trie *> q;
char keyword[210];
char str[maxn];
void insert(char *str,int x)
{
    trie *p=root;
    int i,k,len=strlen(str);
    for(i=0;i<len;i++)
    {
        k=str[i]-' ';
        if(!p->go[k])
        {
            p->go[k]=newnode();
        }
        p=p->go[k];
    }
    p->flag=x;
}
void build_ac_automation()
{
    int i;
    root->fail=NULL;
    q.push(root);
    while(!q.empty())
    {
        trie *tmp=q.front();q.pop();
        trie *p=NULL;
        for(i=0;i<knum;i++)
        {
            if(tmp->go[i])
            {
                if(tmp==root)
                tmp->go[i]->fail=root;
                else
                {
                    p=tmp->fail;
                    while(p)
                    {
                        if(p->go[i])
                        {
                            tmp->go[i]->fail=p->go[i];
                            break;
                        }
                        p=p->fail;
                    }
                    if(p==NULL)
                    tmp->go[i]->fail=root;
                }
                q.push(tmp->go[i]);
            }
        }
    }
}
int vis[510];
int solve()
{
    int i,len=strlen(str),tru=0;
    trie *p=root;
    for(i=0;i<len;i++)
    {
        int k=str[i]-' ';
        while(p!=root&&p->go[k]==NULL)
        p=p->fail;
        p=p->go[k];
        p=(p==NULL)?root:p;
        trie *tmp=p;
        while(tmp!=root)
        {
            if(tmp->flag)
            {
                vis[tmp->flag]=1,tru=1;
            }
            tmp=tmp->fail;
        }
    }
    return tru;
}
int main()
{
   
    int n,i;
    while(scanf("%d",&n)!=EOF)
    {tot=0;
    root=newnode();
    for(i=1;i<=n;i++)
    {
        scanf("%s",keyword);
        insert(keyword,i);
    }
    build_ac_automation();
    int qq,ans=0;
    scanf("%d",&qq);
    for(i=1;i<=qq;i++)
    {
        memset(vis,0,sizeof(vis));
        scanf("%s",str);
        if(solve())
        {
            printf("web %d:",i);
            ans++;
            for(int j=1;j<=n;j++)
            if(vis[j])
            printf(" %d",j);
            printf("\n");
        }
    }
    printf("total: %d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(hdu 2896 病毒侵袭 (AC自动机))