zoukankan      html  css  js  c++  java
  • 【洛谷3796】【模板】AC自动机(加强版)

    点此看题面

    大致题意: 一道模板题,给你(N)个模式串和一个文本串,要你求出在文本串中出现次数最多的若干个模式串并输出它们。

    (AC)自动机

    都说了是(AC)自动机的模板题,做法肯定是(AC)自动机。

    题解

    我们可以考虑在将每个模式串插入(Trie)后,记录下每个模式串最后到达的节点。

    然后,在(AC)自动机时,将每一个经过的节点的访问次数加1。

    最后统计答案时,只要求出最后到达的节点被访问次数最大的若干个模式串并输出即可,应该可以算是一道比较裸的模板题。

    代码

    #include<bits/stdc++.h>
    #define max(x,y) ((x)>(y)?(x):(y))
    #define min(x,y) ((x)<(y)?(x):(y))
    #define LL long long
    #define swap(x,y) (x^=y,y^=x,x^=y)
    #define pc(ch) (pp_<100000?pp[pp_++]=(ch):(fwrite(pp,1,100000,stdout),pp[(pp_=0)++]=(ch)))
    #define N 150
    #define SUM 1000000
    int pp_=0;char pp[100000];
    using namespace std;
    int n,tot=1,rt=1,ans=0,f[N+5];
    struct Trie
    {
        int Son[26],Vis,Next;
    }node[SUM+5];
    string s[N+5],st;
    queue<int> q;
    vector<int> res;
    inline void write(int x)
    {
        if(x>9) write(x/10);
        pc(x%10+'0');
    }
    inline void ps(string x)
    {
        register int i,len=x.length();
        for(i=0;i<len;++i) pc(x[i]);
    }
    inline void Insert(int pos,string s)//将编号为pos的模式串s插入字典树中
    {
        register int i;int x=rt;
        for(i=0;i<s.length();++i)
        {
            int p=s[i]-97;
            if(!node[x].Son[p]) node[x].Son[p]=++tot;
            x=node[x].Son[p];
        }
        f[pos]=x;//记录当前模式串最后到达的节点
    }
    inline void GetNext()//求出失配指针
    {
        register int i,k;q.push(rt);
        while(!q.empty())
        {
            k=q.front(),q.pop();
            for(i=0;i<26;++i)
            {
                if(k^rt)
                {
                    if(!node[k].Son[i]) node[k].Son[i]=node[node[k].Next].Son[i];
                    else node[node[k].Son[i]].Next=node[node[k].Next].Son[i],q.push(node[k].Son[i]);
                }
                else 
                {
                    if(!node[k].Son[i]) node[k].Son[i]=rt;
                    else node[node[k].Son[i]].Next=rt,q.push(node[k].Son[i]);
                }
            }
        }
    }
    inline void AC_Automation()//AC自动机的核心代码
    {
        register int i;int x=rt,len=st.length();
        for(i=0;i<len;++i)
        {
            if(!(x=node[x].Son[st[i]-97])) {x=rt;continue;}
            int p=x;
            while(p^rt) ++node[p].Vis,p=node[p].Next;//将每一个节点的访问次数加1
        }
    }
    int main()
    {
        register int i,j;
        while(~scanf("%d",&n)&&n)
        {
            for(ans=0,i=1;i<=tot;++i) for(node[i].Next=node[i].Vis=j=0;j<26;++j) node[i].Son[j]=0;
            for(tot=i=1;i<=n;++i) cin>>s[i],Insert(i,s[i]);
            for(cin>>st,GetNext(),AC_Automation(),i=1;i<=n;++i) 
            {
                if(node[f[i]].Vis>ans) ans=node[f[i]].Vis,res.clear(),res.push_back(i);//比较当前模式串所对应的Trie上的节点被访问的次数与ans的大小,如果当前模式串出现的次数大于ans,就更新ans
                else if(node[f[i]].Vis==ans) res.push_back(i);//否则,如果当前模式串出现的次数等于ans,就将当前模式串加入最后要输出的数组中
            }
            for(write(ans),pc('
    '),i=0;i<res.size();++i) ps(s[res[i]]),pc('
    ');
        }
        return fwrite(pp,1,pp_,stdout),0;
    }
    
  • 相关阅读:
    hibernate_0100_HelloWorld
    MYSQL子查询的五种形式
    JSF是什么?它与Struts是什么关系?
    nop指令的作用
    htmlparser实现从网页上抓取数据(收集)
    The Struts dispatcher cannot be found. This is usually caused by using Struts tags without the associated filter. Struts tags are only usable when the
    FCKeditor 在JSP上的完全安装
    Java遍历文件夹的2种方法
    充电电池和充电时间说明
    吃知了有什么好处
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu3796.html
Copyright © 2011-2022 走看看