首页 > 代码库 > NYOJ 1085 AC自动机基础模板

NYOJ 1085 AC自动机基础模板

今天学了AC自动机,可以说AC自动机是把匹配的串建立成为一颗trie,然后就和kmp 是一样的

题意:判断在一篇文章中有多少单词出现过,并输出来

#include<cstdio>
#include<cstring>
#include<map>
#include<queue>
#include<iostream>
using namespace std;
const int maxn = 1000007;
int cnt;
struct Node{
    Node *fail;
    Node *next[27];
    int count,id;
    Node(){
        memset(next,NULL,sizeof(next));
        fail = NULL;
        count = 0 ,id = -1;
    }
};
char word[200][108];
int keymap[200],ret[200];
char str[maxn];
int Max;
void insert(int pos,char *str,Node *root){
    Node *p = root;
    int i=0,index;
    while(str[i]){
        index = str[i] - 'a';
        if(p -> next[index] == NULL)
            p -> next[index] = new Node();
        p = p->next[index];i++;
    }
    if(!p->count){
        p->id = cnt++;
        p ->count = 1;
    } keymap[pos] = p->id;
}
void Build_AC_auto(Node *root){
    queue <Node*> s;
    root -> fail = NULL;
    s.push (root);
    while(!s.empty()){
        Node *tmp = s.front();s.pop();
        Node *p   = NULL;
        for(int i=0;i<26;i++){
            if(tmp ->next[i]){
                if(tmp == root)tmp->next[i]->fail = root;
                else {
                    p = tmp->fail;
                    while(p){
                        if(p->next[i]){
                            tmp -> next[i] -> fail = p -> next[i];
                            break;
                        }
                        p = p -> fail;
                    }
                    if(!p)tmp->next[i]->fail = root;
                }
                s.push(tmp -> next[i]);
            }
        }
    }
}
void query(Node *root){
    int i=0;
    Node *p = root;
    while(str[i]){
        int index = str[i] - 'a';
        while(!p->next[index] && p!=root)p = p->fail;
        p = p->next[index];
        p = (p == NULL) ? root : p;
        Node *tmp = p;
        while(tmp !=root ){//puts("yes");
            if(tmp ->count){
               ret[tmp ->id]++;
               if(ret[tmp ->id]> Max){
                Max = ret[tmp -> id];
               }
            }
            tmp = tmp->fail;
        }
        i++;
    }
}
int main(){
    int t,n,m;
    freopen("input.txt","r",stdin);
    scanf("%d",&t);
    while(t --){
        Max = 0;cnt =0 ;
        Node *root = new Node();
        scanf("%d",&n);
       memset(ret,0,sizeof(ret));
       for(int i=0;i<n;i++){
            scanf("%s",word[i]);
            insert(i,word[i],root);
       }
        Build_AC_auto(root);
        scanf("%s",str);
        query(root);
        printf("%d\n",Max);
        for(int i=0;i<n;i++){
            if(ret[keymap[i]]== Max){
                printf("%s\n",word[i]);
            }
        }
    }
}


NYOJ 1085 AC自动机基础模板