HDU 2222 最简单的AC自动机套模板应用

HDU 2222 题意:给出N(N<=10,000)个单词,每个单词长度不超过50。再给出一个字符串S,字符串长度不超过1,000,000。问有多少个单词出现在了字符串S中。(单词可能重复,单词在S中允许重叠)

我们在val[]数组中记录重复的个数

因为在主串对他进行匹配时,匹配到一次后这个重复次数就不应该继续添加了,所以在query中val[]要对它进行清零操作

#include <cstdio>

#include <cstring>

#include <queue>

using namespace std;

#define N 500005

char str[1000005];

struct AC{

    int ch[N][26],fail[N],val[N],last[N],tmp,root;

    int newnode(){

        val[tmp]=0;

        memset(ch[tmp],0,sizeof(ch[tmp]));

        return tmp++;

    }

    void init(){

        tmp=0;

        root=newnode();

    }

    void add(char *s){

        int len=strlen(s);

        int now=root;

        for(int i=0;i<len;i++){

            int &k=ch[now][s[i]-'a'];

            if(!k) k=newnode();

            now=k;

        }

        val[now]++;

    }

    void get_fail(){

        fail[root]=root;

        queue<int> q;

        for(int i=0;i<26;i++){

            int v=ch[root][i];

            if(v)

                fail[v]=last[v]=0,q.push(v);

        }

        while(!q.empty()){

            int now=q.front();

            q.pop();

            for(int i=0;i<26;i++){

                int v=ch[now][i];

                if(!v) ch[now][i]=ch[fail[now]][i];

                else{

                    fail[v]=ch[fail[now]][i];

                    last[v]=val[fail[v]]?fail[v]:last[fail[v]];

                    q.push(v);

                }

            }

        }

    }

    int query(char *str){

        int len=strlen(str);

        int now=root,ret=0;

        for(int i=0;i<len;i++){

            now=ch[now][str[i]-'a'];

            int k=now;

            while(k!=root&&val[k]){//这是要循环到找到fail值为root的时候或者找到匹配的字符串的时候,否则一直向前找fail值,

                ret+=val[k];

                val[k]=0;

                k=last[k];

            }

        }

        return ret;

    }

}ac;

int main()

{

    int T,n;

    scanf("%d",&T);

    while(T--){

        ac.init();

        scanf("%d",&n);

        for(int i=0;i<n;i++){

            scanf("%s",str);

            ac.add(str);

        }

        ac.get_fail();

        scanf("%s",str);

        int ans=ac.query(str);

        printf("%d\n",ans);

    }

    return 0;

}
View Code

 

你可能感兴趣的:(AC自动机)