病毒侵袭---hdu2896(AC自动机)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896

输入的字符是所有可见的ASCII码(共有127个)所以要注意一下;

把结果存到一个数组中,然后输出;

ac自动机详解:http://www.cnblogs.com/zhengguiping--9876/p/4854752.html

要用c++交,G++会MLE的;

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;

const int N = 1e4+10;
int vis[N], a[N], cnt;
char s[N];
struct node
{
    int leaf;
    node *next[127],*fail;
};

void AddTrie(char s[], node *root, int num)
{
    node *p = root;
    for(int i=0; s[i]; i++)
    {
        int k = (int)s[i];
        if(p->next[k]==NULL)
            p->next[k] = new node();
        p = p->next[k];
    }
    p->leaf = num;
}
void GetFail(node *root)
{
    node *p, *q;
    queue<node*>Q;
    Q.push(root);
    while(Q.size())
    {
        p = Q.front(); Q.pop();
        for(int i=0; i<127; i++)
        {
            if(p->next[i]!=NULL)
            {
                q = p->fail;
                while(q!=NULL)
                {
                    if(q->next[i]!=NULL)
                    {
                        p->next[i]->fail = q->next[i];
                        break;
                    }
                    q = q->fail;
                }
                if(q==NULL)
                    p->next[i]->fail = root;
                Q.push(p->next[i]);
            }
        }
    }
}

void Query(char s[], node *root)
{
    node *p = root, *q;
    for(int i=0; s[i]; i++)
    {
        int k = (int)s[i];

        while(p->next[k] == NULL && p!=root)///如果匹配不成功,那么就走失败路径,沿着fail指针走,一直到找到或者跟结点为止;
            p = p->fail;
        p = p->next[k];
        if(p==NULL)
            p = root;
        q = p;
        while(q!=root)
        {
            if(q->leaf && !vis[q->leaf])
            {
                a[cnt++] = q->leaf;
                vis[q->leaf] = 1;
            }
            q = q->fail;
        }
    }
}
void FreeTrie(node *root)
{
    node *p = root;
    for(int i=0; i<127; i++)
    {
        if(p->next[i]!=NULL)
            FreeTrie(p->next[i]);
    }
    free(p);
}
int main()
{
    int n, m;
    while(scanf("%d", &n)!=EOF)
    {
        node *root = new node();
        for(int i=1; i<=n; i++)
        {
            scanf("%s", s);
            AddTrie(s, root, i);
        }
        GetFail(root);
        scanf("%d", &m);
        int ans = 0;
        for(int i=1; i<=m; i++)
        {
            scanf("%s", s);
            memset(a, 0, sizeof(a));
            memset(vis, 0, sizeof(vis));
            cnt = 0;
            Query(s, root);
            if(cnt)
            {
                ans++;
                printf("web %d:", i);
                sort(a, a+cnt);
                for(int j=0; j<cnt; j++)
                    printf(" %d", a[j]);
                printf("\n");
            }
        }
        printf("total: %d\n", ans);
        FreeTrie(root);
    }
    return 0;
}
View Code

 

posted @ 2015-10-05 19:03  西瓜不懂柠檬的酸  Views(170)  Comments(0Edit  收藏  举报
levels of contents