码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 2896 病毒侵袭 AC自动机

时间:2014-07-22 23:55:57      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:blog   http   io   2014   for   re   

http://acm.hdu.edu.cn/showproblem.php?pid=2896


对于hdu oj...发现如果数组越界,还有数组下标为负数 ,可能返回的Judge结果都是WA而不是RE。。。这道题WA了几次,因为

    inline int idx(char c) {
        //return c-'a';  //这里一定小心,如果没有给定字符范围的话,直接return c;
    //因为可能出现负的...病毒侵袭那题就是
        return c;
    }

通过这题学到的:
1、通过cnt数组在O(n)时间内显示所有单词编号由小到大--如果用map存储单词的话,当然也可以按输入顺序存储顺序输出;

2、AC自动机注意首先看字符范围,定下SIGMA_SIZE以及idx函数写法

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

const int SIZE = 10000+10;
const int SIGMA_SIZE = 128;
const int MAXNODE = 61000;
//const int MAXS = 150 + 10;
int maxv;
struct AC
{
    int f[MAXNODE];
    int ch[MAXNODE][SIGMA_SIZE];
    int val[MAXNODE];
    int last [MAXNODE];
    int cnt[MAXNODE];
    int sz;
    void init()
    {
        sz=1;
        memset(ch[0],0,sizeof(ch[0]));
        memset(cnt,0,sizeof(cnt));
        val[0]=f[0]=last[0]=0;
    }
    void clear()
    {
        memset(cnt,0,sizeof(cnt));
    }
    inline int idx(char c) {
        //return c-'a';  //这里一定小心,如果没有给定字符范围的话,直接return c;
    //因为可能出现负的...病毒侵袭那题就是
        return c;
    }
    void insert(char *s, int v)
    {
        int u=0,n=strlen(s);
        for(int i=0;i<n;i++)
        {
            int c=idx(s[i]);
            if(!ch[u][c])
            {
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz]=0;
                ch[u][c]=sz++;
            }
            u=ch[u][c];
        }
        val[u]=v;
    }
    void getfail()
    {
        queue<int>q;
        f[0]=0;
        for(int c=0;c<SIGMA_SIZE;c++)
        {
            int u=ch[0][c];
            if(u)
            {
                f[u]=0;
                q.push(u);
                last[u]=0;
            }
        }
        while(!q.empty())
        {
            int r=q.front();q.pop();
            for(int c=0;c<SIGMA_SIZE;c++)
            {
                int u=ch[r][c];
                if(!u)continue;
                q.push(u);
                int v=f[r];
                while(v && !ch[v][c])v=f[v];
                f[u]=ch[v][c];
                last[u]=val[f[u]]?f[u]:last[f[u]];
            }
        }

    }
            void print(int j)
        {
            if(j)
            {
                maxv=max(val[j],maxv);
                cnt[val[j]]++;
                print(last[j]);
            }
        }
        void find(char *T)
        {
            int n=strlen(T);
            int j=0;
            for(int i=0;i<n;i++)
            {
                int c=idx(T[i]);
                while(j && !ch[j][c])j=f[j];
                j=ch[j][c];
                if(val[j])
                    print(j);
                else
                    if(last[j])print(last[j]);
            }
        }
};

AC ac;

int main()
{
    //freopen("hdu2896.txt","r",stdin);
    int n,m;
    char str[SIZE];
    while(scanf("%d",&n) !=EOF)
    {

        ac.init();
        for(int i=1;i<=n;i++)
        {
            scanf("%s",str);
            ac.insert(str,i);
        }
        ac.getfail();
        scanf("%d",&m);
        int wcnt=0,flag=0;

        for(int i=1;i<=m;i++)
        {
            maxv=0;
            flag=0;
            ac.clear();
            scanf("%s",str);
            ac.find(str);

            for(int j=1;j<=maxv;j++)
            {
                if(ac.cnt[j])
                {
                    flag++;
                    if(flag==1)printf("web %d: ",i);
                    if(j<maxv)printf("%d ",j);
                    else printf("%d\n",j);
                }
            }
            if(flag)wcnt++;
        }
        printf("total: %d\n",wcnt);
    }
    return 0;
}


hdu 2896 病毒侵袭 AC自动机,布布扣,bubuko.com

hdu 2896 病毒侵袭 AC自动机

标签:blog   http   io   2014   for   re   

原文地址:http://blog.csdn.net/u011026968/article/details/38051293

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!