[模板]AC自动机(1)

题目描述

给定一个文本串和多个模式串,求有几个模式串出现在文本串中

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 1000005

char s[MAXN];
int N;
struct queue{
    int que[MAXN];int head,tail;
    queue():head(1),tail(0){}
    inline void pop(){head++;}
    inline int front(){return que[head];}
    inline void push(int x){que[++tail]=x;}
    inline bool empty(){return head>tail;}
}q;
struct Auto{
    
    int trie[26][MAXN],val[MAXN],fail[MAXN],tot;
    Auto():tot(0){}

    inline void ins(){
        int _next = 0;int len = std::strlen(s);
        for(register int i=0;i<len;++i){
            int c = s[i]-'a';
            if(!trie[c][_next])trie[c][_next] = ++tot;
            _next = trie[c][_next];
        }
        val[_next]++;
    }

    inline void make_fail(){
        for(register int i=0;i<26;++i){
            if(trie[i][0]){
                q.push(trie[i][0]);
                fail[trie[i][0]] = 0;
            }
        }
        while(!q.empty()){
            int u = q.front();q.pop();
            for(register int i=0;i<26;++i){
                if(trie[i][u]){
                    q.push(trie[i][u]);
                    fail[trie[i][u]] = trie[i][fail[u]];
                }
                else trie[i][u] = trie[i][fail[u]];
            }
        }
    }

    inline int find(){
        int ans = 0;int len = std::strlen(s);int _next = 0;
        for(register int i=0;i<len;++i){
            _next = trie[s[i]-'a'][_next];
            for(register int pos=_next;pos&&val[pos]!=-1;pos=fail[pos]){
                ans+=val[pos];
                val[pos] = -1;
            }
        }
        return ans;
    }
}AC;

int main(){

    scanf("%d\n",&N);
    for(register int i=1;i<=N;++i){
        scanf("%s",s);
        AC.ins();
    }
    AC.make_fail();
    scanf("%s",s);
    int ans = AC.find();
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Neworld2002/p/9499332.html