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

     字符串匹配[作业部落]

    单纯判断模式串是否在文本串中出现:

    #define rg register
    #define _ 1000001
    using namespace std;
    int n,num,team[_<<1],result;
    char aa[_];
    struct AC_aotomatic
    {
        int fail,son[26],end,it;//end:有多少个字符串在此点结束
    }trie[_];
    inline int read()
    {
        rg int save=0,w=1;rg char q=getchar();
        while(q<'0'||q>'9'){if(q=='-')w=-1;q=getchar();}
        while(q>='0'&&q<='9')save=(save<<3)+(save<<1)+q-'0',q=getchar();
        return save*w;
    }
    inline void insert(rg int &fa,rg char q)
    {
        if(!trie[fa].son[q-'a'])trie[fa].son[q-'a']=++num;
        fa=trie[fa].son[q-'a'];
        trie[fa].it=q-'a';
    }
    inline void get_fail()
    {
        rg int i,j;
        rg int head=0,tail=0;
        for(i=0;i<26;++i)
        {
            if(trie[0].son[i])
                team[++tail]=trie[0].son[i], trie[trie[0].son[i]].fail=0;
                //第一层的fail必须指向root(即0)!!!
                //假如到第一层就匹配失败了,自然要从第一层重新找一个点匹配
        }
        do
        {
            head++;
            rg int u=team[head];
            for(i=0;i<26;++i)
            {
                if(trie[u].son[i])
                {
                    trie[trie[u].son[i]].fail=trie[trie[u].fail].son[i];
                    //和KMP相像的是,son[i]的fail指向的是 前面已有后缀与son[i]的前一部分相同,而自己等于son[i]的点,也就可以待匹配
                    team[++tail]=trie[u].son[i];
                }
                else
                    trie[u].son[i]=trie[trie[u].fail].son[i];
                    //当前节点的这个子节点指向 当前节点的fail指针指向的点 的这个子节点 
            }
        }while(head<tail);
    }
    inline void doit()
    {
        rg int i,j=0;
        rg int l=strlen(aa);
    //    cout<<aa<<endl;
        for(i=0;i<l;++i)
        {
            j=trie[j].son[aa[i]-'a'];//跳儿子,若son[aa[i]-'a']为空,就指回根了
            for(rg int t=j; t&&trie[t].end!=-1 ;t=trie[t].fail)//跳fail指针
            {
                result+=trie[t].end;
                trie[t].end=-1;
                //因为这个循环前面一行有个跳儿子的操作,所以如果跳儿子跳到根了,可能会把fail指针已经跳到过的字符串再跳一遍,所以在此加一个便于判定走过的操作
            }
        }
        printf("%d
    ",result);
    }
    int main()
    {
        n=read();
        rg int i,j;
        for(i=1;i<=n;++i)
        {
            rg char q=getchar();rg int fa=0;
            while(q<'a'||q>'z')q=getchar();
            while(q>='a'&&q<='z')insert(fa,q),q=getchar();
            trie[fa].end++;
    //        cout<<fa<<' '<<trie[fa].end<<endl;
        }
        rg char q=getchar();j=-1;
        while(q<'a'||q>'z')q=getchar();
        while(q>='a'&&q<='z')aa[++j]=q,q=getchar();
        get_fail();
        doit();
        return 0;
    }

    计算模式串出现次数:

    #define rg register
    #define _ 10000005
    #define max(x,y) x<y?y:x
    using namespace std;
    int n,ans[1000],to[11],team[_],maxx,num,record[1000],num_of_edges;
    char aa[_],ss[11][51];
    struct pp
    {
        int next,to;
    }edge[_<<1];
    struct AC_Automatic
    {
        int fail,son[27],end;
    }trie[1000];
    inline int read()
    {
        rg int save=0,w=1;rg char q=getchar();
        while(q<'0'||q>'9'){if(q=='-')w=-1;q=getchar();}
        while(q>='0'&&q<='9')save=(save<<3)+(save<<1)+q-'0',q=getchar();
        return save*w;
    }
    inline void insert(rg int &i,rg char q)
    {
        if(!trie[i].son[q-'a'])trie[i].son[q-'a']=++num;
        i=trie[i].son[q-'a'];
    }
    inline void get_fail()
    {
        rg int head=0,tail=0,i;
        for(i=0;i<26;++i)
        {
            if(trie[0].son[i])
                trie[trie[0].son[i]].fail=0,team[++tail]=trie[0].son[i];
        }
        do
        {
            head++;
            rg int u=team[head];
            for(i=0;i<26;++i)
            {
                if(trie[u].son[i])
                {
                    team[++tail]=trie[u].son[i];
                    trie[trie[u].son[i]].fail=trie[trie[u].fail].son[i];
                }
                else
                    trie[u].son[i]=trie[trie[u].fail].son[i];
            }
        }while(head<tail);
    }
    inline void doit()
    {
        rg int i,j=0;
        rg int l=strlen(aa);
        for(i=0;i<l;++i)
        {
            j=trie[j].son[aa[i]-'a'];
            ans[j]++;
        }
    }
    inline void add(rg int from,rg int to)
    {
        edge[++num_of_edges]=(pp){record[from],to};
        record[from]=num_of_edges;
    }
    void dfs(rg int i)
    {
        for(rg int j=record[i];j;j=edge[j].next)
        {
            rg int to=edge[j].to;
            dfs(to);
            ans[i]+=ans[to];
        }
    }
    inline void solve()
    {
        rg int i,j;
        for(i=1;i<=num;++i)
            add(trie[i].fail,i);
        dfs(0);
    }
    int main()
    {
        n=read();
    //        cout<<"________"<<n<<"
    ";
        rg int i,j;
        for(i=1;i<=n;++i)
        {
            rg char q=getchar();rg int fa=0,j=-1;
            while(q<'a'||q>'z')q=getchar();
            while(q>='a'&&q<='z')ss[i][++j]=q,insert(fa,q),q=getchar();
    //            cout<<ss[i]<<endl;
            trie[fa].end++;
            to[i]=fa;
        }
        rg char q=getchar();j=-1;
        while(q<'a'||q>'z')q=getchar();
        while(q>='a'&&q<='z')aa[++j]=q,q=getchar();
    //        cout<<aa<<endl;
        get_fail();
        doit();
        solve();
        for(i=1;i<=n;++i)
            printf("%s %d
    ",ss[i],ans[to[i]]);
        return 0;
    }
  • 相关阅读:
    开源监控软件之争
    为什么很多公司都自主开发监控系统?
    为 UWP 应用提供的 .NET 网络 API
    亲,根据二八定律,你的监控工具可能白装了哦
    PHP7正式版测试,性能惊艳!
    Java Web 前端高性能优化(一)
    天下武功无坚不破,唯快不破!
    告警信息大爆炸,运维解放秘籍!
    第33节:Java面向对象中的异常
    第33节:Java面向对象中的异常
  • 原文地址:https://www.cnblogs.com/c-wen/p/9367243.html
Copyright © 2011-2022 走看看