hdu 3065 病毒侵袭持续中【AC自动机】

<题目链接>

题目大意:

小t非常感谢大家帮忙解决了他的上一个问题。然而病毒侵袭持续中。在小t的不懈努力下,他发现了网路中的“万恶之源”。这是一个庞大的病毒网站,他有着好多好多的病毒,但是这个网站包含的病毒很奇怪,这些病毒的特征码很短,而且只包含“英文大写字符”。当然小t好想好想为民除害,但是小t从来不打没有准备的战争。知己知彼,百战不殆,小t首先要做的是知道这个病毒网站特征:包含多少不同的病毒,每种病毒出现了多少次。大家能再帮帮他吗?
#include <bits/stdc++.h>
using namespace std;

const int N = 55*1000;
int n,num[1005];
char words[1005][55];

struct Trie{
    int nxt[N][128],fail[N],end[N];
    int root,pos;
    int newnode(){
        for(int i=0;i<128;i++)
            nxt[pos][i]=-1;
        end[pos++]=0;
        return pos-1;
    }
    void init(){
        pos=0;root=newnode();
    }
    void insert(char s[],int id){
        int len=strlen(s);
        int now=root;
        for(int i=0;i<len;i++){
            int to=s[i];
            if(nxt[now][to] == -1)
                nxt[now][to]=newnode();
            now=nxt[now][to];
        }
        end[now]=id;
    }
    void build(){
        fail[root]=root;
        queue<int>q;
        for(int i=0;i<128;i++){
            if(nxt[root][i]==-1)
                nxt[root][i]=root;
            else{
                fail[nxt[root][i]]=root;
                q.push(nxt[root][i]);
            }
        }
        while(!q.empty()){
            int now=q.front();q.pop();
            for(int i=0;i<128;i++){
                if(nxt[now][i]==-1)
                    nxt[now][i]=nxt[fail[now]][i];
                else{
                    fail[nxt[now][i]]=nxt[fail[now]][i];
                    q.push(nxt[now][i]);
                }
            }
        }
    }
    void query(char s[]){
        int len=strlen(s);
        int now=root;
        for(int i=0;i<len;i++){
            now=nxt[now][s[i]];
            int tmp=now;
            while(tmp!=root){
                if(end[tmp]!=0)
                    num[end[tmp]]++;
                //若每个模式串只在主串中匹配一次则加上 end[temp]=0; 
                tmp=fail[tmp];
            }
        }
        for(int i=1;i<=n;i++)
            if(num[i]!=0)
                printf("%s: %d
",words[i],num[i]);
    }
}ac;

char buf[int(2e6+5)];
int main(){
    while(~scanf("%d",&n)){
        memset(num,0,sizeof(num));
        ac.init();
        for(int i=1;i<=n;i++){
            scanf("%s",words[i]);
            ac.insert(words[i],i);
        }
        ac.build();
        scanf("%s",buf);
        ac.query(buf);
    }
}
原文地址:https://www.cnblogs.com/00isok/p/9428706.html