[AC自动机]hdoj 3065:病毒侵袭持续中

大致题意:

    给出n个模式串,一个文本串,分别求出每个文本串子在模式串中出现的次数。

 

大致思路:

    基本的AC自动机,要修改一些地方。

 

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include <algorithm>
using namespace std;
const int inf=1<<28;
const int nMax=1500;
const int mMax=2000000;
class node{
public:
    int id;
    int count;  //前缀记录标志
    node *next[30],*fail;
    node(){
        id=-1;
        count=0;
        fail=NULL;
        for(int i=0;i<30;i++)next[i]=NULL;
    }
}*root,*que[mMax];
int cnt;
void insert(char *s){    //构造前缀树
    int i;
    node *r=root;
    int l=strlen(s);
    for(i=0;i<l;i++){
        int loc=s[i]-'A';
        if(r->next[loc]==NULL){
            r->next[loc]=new node();
        }
        r=r->next[loc];
    }
    if(r->id==-1){
        r->id=cnt;
        cnt++;
    }
    r->count++;
}

void acAuto(){      //用bfs为每个节点设定fail指针
    int i,head=0,tail=0;
    node *p,*tmp;
    root->fail=NULL;
    que[tail++]=root;
    while(head<tail){
        tmp=que[head++];
        for(i=0;i<30;i++){
            if(tmp->next[i]==NULL)continue;
            if(tmp==root){
                tmp->next[i]->fail=root;
            }
            else {
                for(p=tmp->fail;p!=NULL;p=p->fail){
                    if(p->next[i]!=NULL){
                        tmp->next[i]->fail=p->next[i];
                        break;
                    }
                }
                if(p==NULL){
                    tmp->next[i]->fail=root;
                }
            }
            que[tail++]=tmp->next[i];
        }
    }
}
int vis[nMax];
void search(char *msg){
    int i,idx;
    node *p=root,*tmp;
    for(i=0;msg[i];i++){
        idx=msg[i]-'A';
        if(idx<0||idx>26)idx=27;
        while(p->next[idx]==NULL&&p!=root){
            p=p->fail;
        }
        p=p->next[idx];
        if(p==NULL)p=root;
        for(tmp=p;tmp!=NULL;tmp=tmp->fail){//&&tmp->count!=-1   因为这里需要求的是该字符串出现的次数
            if(tmp->id!=-1)vis[tmp->id]++;   //也就是字符需要重复出现,所以这句要注释掉
        }
    }
}

char str[nMax][55],text[mMax];
int main(){
    int n,i,j,flag;
    while(scanf("%d",&n)!=EOF){
        cnt=1;
        root=new node();
        memset(vis,0,sizeof(vis));
        for(i=1;i<=n;i++){
            scanf("%s",str[i]);
            insert(str[i]);
        }
        acAuto();
        scanf("%s",text);
        search(text);
        flag=1;
        for(i=1;i<=n;i++){
            if(vis[i]!=0){
                flag=0;
                printf("%s: %d\n",str[i],vis[i]);
            }
        }
        if(flag)printf("\n");
    }
    return 0;
}
 

你可能感兴趣的:(数据结构,ACM,AC自动机,病毒侵袭持续中,hdoj 3065)