AC自动机例题

Posted lizehon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AC自动机例题相关的知识,希望对你有一定的参考价值。

P3808 [模板]AC自动机(简单版)
[题目描述]
给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF=1e9+7;
inline LL read(){
    register LL x=0,f=1;register char c=getchar();
    while(c<48||c>57){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
    return f*x;
}

const int MAXN=1e6+5;
const int MAXV=26;

namespace ACzdj{
    struct Trie{
        int v[MAXV];
        int fail,end;
    }AC[MAXN];
    int Ncnt;
    inline void build(string s){
        int cur=0,l=s.length();
        for(int i=0;i<l;i++){
            if(!AC[cur].v[s[i]-‘a‘])
                AC[cur].v[s[i]-‘a‘]=++Ncnt;
            cur=AC[cur].v[s[i]-‘a‘];
        }
        AC[cur].end+=1;
    }
    inline void Get_fail(){
        queue <int> q;
        for(int i=0;i<26;i++)
            if(AC[0].v[i]){
                AC[AC[0].v[i]].fail=0;
                q.push(AC[0].v[i]);
            }
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=0;i<26;i++){
                if(AC[u].v[i]){
                    AC[AC[u].v[i]].fail=AC[AC[u].fail].v[i];
                    q.push(AC[u].v[i]);
                }
                else
                    AC[u].v[i]=AC[AC[u].fail].v[i];
            }
        }
    }
    inline int query(string s){
        int res=0;
        int l=s.length(),cur=0;
        for(int i=0;i<l;i++){
            cur=AC[cur].v[s[i]-‘a‘];
            for(int t=cur;t&&AC[t].end!=-1;t=AC[t].fail){
                res+=AC[t].end;
                AC[t].end=-1;
            }
        }
        return res;
    }
}using namespace ACzdj;

int n;
string s;

int main(){
    n=read();
    for(int i=1;i<=n;i++){
        cin>>s;
        build(s);
    }
    AC[0].fail=0;
    Get_fail();
    cin>>s;
    printf("%d
",query(s));
}

P3796 [模板]AC自动机(加强版)

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF=1e9+7;
inline LL read(){
    register LL x=0,f=1;register char c=getchar();
    while(c<48||c>57){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
    return f*x;
}

const int MAXN=150000;
const int MAXM=155;
const int MAXV=26;

struct Node{
    int num,id;
    friend bool operator < (Node a,Node b){
        if(a.num==b.num) return a.id<b.id;
        return a.num>b.num;
    }
}ans[MAXM];

namespace ACzdj{
    struct Trie{
        int v[MAXV];
        int fail,end;
    }AC[MAXN];
    int Ncnt;
    inline void clear(int x){
        for (register int i = 0; i < 26; ++i)
            AC[x].v[i] = 0;
        AC[x].fail=0,AC[x].end=0;
    }
    inline void build(const string& s,int id){
        int cur=0,l=s.length();
        for(int i=0;i<l;i++){
            if(!AC[cur].v[s[i]-‘a‘]){
                AC[cur].v[s[i]-‘a‘]=++Ncnt;
                clear(Ncnt);
            }
            cur=AC[cur].v[s[i]-‘a‘];
        }
        AC[cur].end=id;
    }
    inline void Get_fail(){
        queue<int> q;
        for(int i=0;i<26;i++)
            if(AC[0].v[i]){
                AC[AC[0].v[i]].fail=0;
                q.push(AC[0].v[i]);
            }
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=0;i<26;i++){
                if(AC[u].v[i]){
                    AC[AC[u].v[i]].fail=AC[AC[u].fail].v[i];
                    q.push(AC[u].v[i]);
                }
                else
                    AC[u].v[i]=AC[AC[u].fail].v[i];
            }
        }
    }
    inline void query(const string& s){
        int l=s.length(),cur=0;
        for(int i=0;i<l;i++){
            cur=AC[cur].v[s[i]-‘a‘];
            for(int t=cur;t;t=AC[t].fail)
                ans[AC[t].end].num++;
        }
    }
}using namespace ACzdj;

int n;
string s[MAXM];

int main(){
//  freopen("trie.in","r",stdin);
//  freopen("trie.out", "w", stdout);
    while(n = read()){
        clear(Ncnt=0);
        for(int i=1;i<=n;i++){
            cin>>s[i];
            ans[i].num=0,ans[i].id=i;
            build(s[i],i);
        }
        AC[0].fail=0;
        Get_fail();
        cin>>s[0];
        query(s[0]);
        sort(ans+1,ans+n+1);
        printf("%d
",ans[1].num);
        cout<<s[ans[1].id]<<endl;
        for(int i=2;ans[i].num==ans[i-1].num&&i<=n;i++)
            //printf("%s
",s[ans[i].id]);
            cout<<s[ans[i].id]<<endl;
    }
}


以上是关于AC自动机例题的主要内容,如果未能解决你的问题,请参考以下文章

AC自动机入门和几道例题

「学习笔记」AC 自动机

POJ2778DNA Sequence(AC自动机)

HDU3247 Resource Archiver(AC自动机+BFS+DP)

POJ3691DNA repair(AC自动机,DP)

AC自动机板子