zoukankan      html  css  js  c++  java
  • AC自动机

    放三个板子

    板子1:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e6;
    int tire[N][26],fail[N],n,tot=1,end[N],ans;
    char str[N];
    inline void insert(char *a)
    {
        int n=strlen(a+1),p=1;
        for(int i=1;i<=n;++i)
        {
            int ch=a[i]-'a';
            if(!tire[p][ch]) tire[p][ch]=++tot;
            p=tire[p][ch];
        }
        end[p]++;
    }
    inline void get_fail()
    {
        queue<int>q;q.push(1);
        fail[1]=0;
        for(int i=0;i<26;++i) tire[0][i]=1;
        while(!q.empty())
        {
            int x=q.front();q.pop();
            for(int i=0;i<26;++i)
            {
                if(!tire[x][i]) {tire[x][i]=tire[fail[x]][i];continue;}
                fail[tire[x][i]]=tire[fail[x]][i];q.push(tire[x][i]); 
            }
        }
    }
    inline int AC(char *a)
    {
        int n=strlen(a+1),p=1;
        for(int i=1;i<=n;++i)
        {
            int ch=a[i]-'a';
            int k=tire[p][ch];
            while(k>1&&end[k]!=-1)
            {
                ans+=end[k];end[k]=-1;
                k=fail[k];
            }
            p=tire[p][ch];
        }
        return ans;
    }
    int main()
    {
        freopen("1.in","r",stdin);
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%s",str+1);
            insert(str);
        }
        get_fail();
        scanf("%s",str+1);
        printf("%d",AC(str));
        return 0;
    } 
    View Code

    板子2:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5,qwq=1e6+10;
    int n,tire[N][26],tot=1,end[N],cnt[N],fail[N];
    char str[200][100];
    char ch[qwq];
    inline void insert(char *a,int s)
    {
        int n=strlen(a+1),p=1;
        for(int i=1;i<=n;++i)
        {
            int ch=a[i]-'a';
            if(!tire[p][ch]) tire[p][ch]=++tot;
            p=tire[p][ch];
        }
        end[p]=s;
    }
    inline void get_fail()
    {
        queue<int>q;q.push(1);
        fail[1]=0;
        for(int i=0;i<26;++i) tire[0][i]=1;
        while(!q.empty())
        {
            int x=q.front();q.pop();
            for(int i=0;i<26;++i)
            {
                if(!tire[x][i]) {tire[x][i]=tire[fail[x]][i];continue;}
                fail[tire[x][i]]=tire[fail[x]][i];q.push(tire[x][i]);
            }
        }
    }
    inline void AC(char *a)
    {
        int m=strlen(a+1),p=1;
        for(int i=1;i<=m;++i)
        {
            int ch=a[i]-'a';
            int k=tire[p][ch];
            while(k>1)
            {
                cnt[end[k]]++;
                k=fail[k];
            }
            p=tire[p][ch];
            //cout<<i<<' '<<cnt[1]<<' '<<cnt[2]<<endl;
        }
        int mx=0;
        for(int i=1;i<=n;++i) mx=max(mx,cnt[i]);
        printf("%d
    ",mx);
        for(int i=1;i<=n;++i)
            if(cnt[i]==mx) printf("%s
    ",str[i]+1);
    }
    int main()
    {
        freopen("1.in","r",stdin);
        while(scanf("%d",&n))
        {
            if(n==0) break;
            memset(tire,0,sizeof(tire));
            memset(fail,0,sizeof(fail));
            memset(end,0,sizeof(end));
            memset(cnt,0,sizeof(cnt));
            tot=1;
            for(int i=1;i<=n;++i)
            {
                scanf("%s",str[i]+1);
                insert(str[i],i);
            }
            get_fail();
            scanf("%s",ch+1);
            AC(ch);
        }
        return 0;
    }
    View Code

    板子3(拓扑优化):

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e6;
    int tire[N][26],fail[N],n,tot=1,end[N],ans;
    char str[N];
    inline void insert(char *a)
    {
        int n=strlen(a+1),p=1;
        for(int i=1;i<=n;++i)
        {
            int ch=a[i]-'a';
            if(!tire[p][ch]) tire[p][ch]=++tot;
            p=tire[p][ch];
        }
        end[p]++;
    }
    inline void get_fail()
    {
        queue<int>q;q.push(1);
        fail[1]=0;
        for(int i=0;i<26;++i) tire[0][i]=1;
        while(!q.empty())
        {
            int x=q.front();q.pop();
            for(int i=0;i<26;++i)
            {
                if(!tire[x][i]) {tire[x][i]=tire[fail[x]][i];continue;}
                fail[tire[x][i]]=tire[fail[x]][i];q.push(tire[x][i]); 
            }
        }
    }
    inline int AC(char *a)
    {
        int n=strlen(a+1),p=1;
        for(int i=1;i<=n;++i)
        {
            int ch=a[i]-'a';
            int k=tire[p][ch];
            while(k>1&&end[k]!=-1)
            {
                ans+=end[k];end[k]=-1;
                k=fail[k];
            }
            p=tire[p][ch];
        }
        return ans;
    }
    int main()
    {
        freopen("1.in","r",stdin);
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%s",str+1);
            insert(str);
        }
        get_fail();
        scanf("%s",str+1);
        printf("%d",AC(str));
        return 0;
    }
    View Code
  • 相关阅读:
    剑指offer——最小的K个数和数组中第K大的元素
    Leetcode刷题指南链接整理
    160. Intersection of Two Linked Lists
    100. Same Tree
    92. Reverse Linked List II
    94. Binary Tree Inorder Traversal
    79. Word Search
    78,90,Subsets,46,47,Permutations,39,40 DFS 大合集
    0x16 Tire之最大的异或对
    0x16 Tire
  • 原文地址:https://www.cnblogs.com/gcfer/p/12739907.html
Copyright © 2011-2022 走看看