AC自动机再加强版

AC自动机

拓扑排序优化,注意拓扑排序前要把所有入度为零的点都加进去

#include<bits/stdc++.h>
using namespace std;
#define maxn 1000005
#define maxm 28
struct AC
{
    int trieN;
    int ch[maxn][maxm];
    int val[maxn];
    int fail[maxn];
    int ans[maxn];
    int in[maxn];///用于拓扑排序
    vector<int> s[maxn];
    int tim[maxn];
    void init()
    {
        trieN=-1;
        newnod();
    }
    int newnod()
    {
        memset(ch[++trieN],0,sizeof ch[0]);
        val[trieN]=fail[trieN]=0;
        tim[trieN]=0;s[trieN].clear();
        return trieN;
    }
    void insert(const string & str,int k)
    {
        int cur=0;
        for(int i=0; i<str.size(); i++)
        {
            int d=str[i]-'a';
            if(!ch[cur][d])
            {
                ch[cur][d]=newnod();
            }
            cur=ch[cur][d];
        }
        val[cur]++;
        s[cur].push_back(k);
    }
    void build()
    {
        queue<int> q;
        for(int i=0; i<maxm; i++)
        {
            if(ch[0][i])
            {
                q.push(ch[0][i]);
            }
        }
       // q.push(0);
        while(!q.empty())
        {
            int cur=q.front();
            q.pop();
            for(int i=0; i<maxm; i++)
            {
                if(ch[cur][i])
                {
                   // cout<<cur<<' '<<i<<endl;
                   //cout<<fail[cur]<<'\n';
                    fail[ch[cur][i]]=ch[fail[cur]][i];
                    in[fail[ch[cur][i]]]++;
                    //cout<<fail[ch[cur][i]]<<"INNNNN"<<'\n';
                    q.push(ch[cur][i]);
                }
                else
                {
                    ch[cur][i]=ch[fail[cur]][i];
                }
            }
        }
    }
    //vector<int>ans;
    //int man=0;
    void topu()
    {
        queue<int>q;
        /*for(int i=1;i<=trieN;i++){
            cout<<i<<"IN"<<in[i]<<'\n';

        }*/
        for(int i=0;i<=trieN;i++){
            if(in[i]==0){
                q.push(i);}}
                while(!q.empty()){

                    int x=q.front();
                      //cout<<x<<" "<<ans[x]<<'\n';
                    q.pop();
                    if(val[x]){
                        for(int i=0;i<s[x].size();i++)
                        tim[s[x][i]]=ans[x];
                    }

                    int y=fail[x];
                    ans[y]+=ans[x];
                    in[y]--;
                    if(in[y]==0)q.push(y);
                }


    }
    void query(const string & str)
    {
        int res=0,cur=0;
        for(int i=0; str[i]; i++)
        {
            int d=str[i]-'a';
            cur=ch[cur][d];
            ans[cur]++;
        }
    }
} ac;
//string A[maxn];
int main()
{
    string s;
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        ac.init();
        //if(n==0)break;
        for(int i=0; i<n; i++)
        {
            cin>>s;
            ac.insert(s,i);
        }
        ac.build();
        cin>>s;
        ac.query(s);
        ac.topu();
        for(int i=0;i<n;i++){
            cout<<ac.tim[i]<<'\n';
        }
    }
}

 

posted @ 2019-08-09 10:12  liulex  阅读(229)  评论(0编辑  收藏  举报