首页 > 代码库 > hdu 3056 病毒侵袭持续中 AC自动机

hdu 3056 病毒侵袭持续中 AC自动机

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


刘汝佳的模板真的很好用,这道题直接过

学到:
cnt数组记录单词出现次数

以及map存储单词编号与字符串,便于处理相关信息

上代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <string>
#include <map>
using namespace std;

const int SIGMA_SIZE=128;
const int MAXNODE = 1005*55;
const int SSIZE = 2000000+100;

struct AC
{
    int f[MAXNODE];
    int ch[MAXNODE][SIGMA_SIZE];
    int cnt[MAXNODE];
    int val[MAXNODE];
    int last[MAXNODE];
    int sz;
    void init()
    {
        memset(cnt,0,sizeof(cnt));
        memset(ch[0],0,sizeof(ch[0]));
        sz=1;
        f[0]=last[0]=val[0]=0;
    }
    inline void clear(){memset(cnt,0,sizeof(cnt));}
    void insert(string s,int v)
    {
        int u=0,n=s.size();
        for(int i=0;i<n;i++)
        {
            int c=s[i];
            if(!ch[u][c])
            {
                val[sz]=0;
                memset(ch[sz],0,sizeof(ch[sz]));
                ch[u][c]=sz++;
            }
            u=ch[u][c];
        }
        val[u]=v;
    }
    void print(int j)
    {
        if(j)
        {
            cnt[val[j]]++;
            print(last[j]);
        }
    }
    void getfail()
    {
        queue<int>q;
        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 find(char *T)
    {
        int n=strlen(T);
        int j=0;
        for(int i=0;i<n;i++)
        {
            int c = 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;
char str[SSIZE];
int main()
{
    //freopen("hdu3056.txt","r",stdin);
    int n;
    string word;
    while(~scanf("%d",&n))
    {
        ac.init();
        map<int, string> ms;
        for(int i=1;i<=n;i++)
        {
            cin >> word;
            ms[i]=word;
            ac.insert(word,i);
        }
        ac.getfail();
        scanf("%s",str);
        ac.find(str);
        for(int i=1;i<=n;i++)
        {
            ////////////////
            //printf("%d %d\n",i,ac.cnt[i]);
            ///////////////////
            if(ac.cnt[i])
            {
                cout << ms[i] << ": " << ac.cnt[i] << endl;
            }
        }
    }
    return 0;
}