• 自动AC机


    洛谷

    构建trie树

    构建fail树

    AC匹配

    #include<bits/stdc++.h>
    #define re return
    #define inc(i,l,r) for(int i=l;i<=r;++i)
    using namespace std;
    template<typename T>inline void rd(T&x)
    {
        char c;bool f=0;
        while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
        x=c^48;
        while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
        if(f)x=-x; 
    }
    
    int n,tot,ans[155];
    char ss[155][75],s[1000005];
    struct node{
        int end,fail,son[26];
    }AC[100005]; 
    
     
    inline void clean(int x)
    {
        for(int i=0;i<=25;++i)
        AC[x].son[i]=0;
        AC[x].fail=0;
        AC[x].end=0;
    }
     
    inline void build(int x)
    {
        int len=strlen(ss[x]);
        int now=0;
        inc(i,0,len-1)//构建trie树 
        {
            if(!AC[now].son[ss[x][i]-'a'])
            {
                AC[now].son[ss[x][i]-'a']=++tot;
                clean(tot);//下一层回档 
            }
            now=AC[now].son[ss[x][i]-'a'];
        }
        AC[now].end=x;//标记访问节点标号 
    }
    
    inline void  Get_fail()
    {
        queue<int>Q;
        inc(i,0,25)//预处理第一层 
        {
            if(AC[0].son[i])
            {
                AC[AC[0].son[i]].fail=0;
                Q.push(AC[0].son[i]);
            }
        }
        while(!Q.empty())
        {
            int u=Q.front();
            Q.pop();
            inc(i,0,25)
            {
                if(AC[u].son[i])//存在 
                {
                    AC[AC[u].son[i]].fail=AC[AC[u].fail].son[i];//子节点的fail指向该父节点的fail 
                    Q.push(AC[u].son[i]);
                }
                else //不存在 
                AC[u].son[i]=AC[AC[u].fail].son[i];//子节点直接指向该fail的son[i] 
            }
        } 
    } 
    
    inline void Get_ans()
    {
        int now=0;
        int len=strlen(s);
        inc(i,0,len-1)
        {
            now=AC[now].son[s[i]-'a'];
            for(int t=now;t;t=AC[t].fail)
            ++ans[AC[t].end];
        }
    }
    int main()
    {
        freopen("in.txt","r",stdin);
        while(2333)
        {
            rd(n);
            if(!n) break;
            tot=0;
            clean(0);//清0 
            inc(i,1,n)
            {
                scanf("%s",ss[i]);
                ans[i]=0;
                build(i);
            }
            AC[0].fail=0;
            Get_fail();
            scanf("%s",s);
            Get_ans(); 
            int maxx=0;
            inc(i,1,n)
                maxx=max(ans[i],maxx);
            printf("%d
    ",maxx);
            
            inc(i,1,n)
            if(ans[i]==maxx)
            printf("%s
    ",ss[i]);
        }
        
        re 0;
    }
  • 相关阅读:
    爱的火花
    为你祝福
    你有成功的强烈愿望吗?人格魅力应该是这样修养而成的
    爱已远走
    我要跳舞
    创业家比商业模式更重要
    月下独酌
    李珊(再帮别人名字作诗)
    分析MSSQL数据库的用户表数和记录数 (转载)
    几个常用的SharePoint对象模型的有用函数
  • 原文地址:https://www.cnblogs.com/lsyyy/p/11375138.html
Copyright © 2020-2023  润新知