zoukankan      html  css  js  c++  java
  • hdu 2222 Keywords Search——AC自动机

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2222

    第一道AC自动机!

    T了无数边后终于知道原来它是把若干询问串建一个自动机,把模式串放在上面跑;而且只走模式串的前缀,用 fail 指针来精准遍历每个前缀的每个后缀,就能行了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e6+5,K=27;
    int T,n,c[N][K],fail[N],ed[N],len,ans,tot;
    int q[N],he,tl;
    char ch[N];
    void init()
    {
        tot=1;ans=he=tl=0;
        memset(c,0,sizeof c);memset(fail,0,sizeof fail);
        memset(ed,0,sizeof ed);
    }
    void insert()
    {
        int nw=1;
        for(int i=1,d;i<=len;i++)
        {
            d=ch[i]-'a';
            if(!c[nw][d])
                c[nw][d]=++tot;
            nw=c[nw][d];
        }
        ed[nw]++;
    }
    void gtfl()
    {
        for(int i=0;i<26;i++)
            if(c[1][i])
            {
                q[++tl]=c[1][i];
                fail[c[1][i]]=1;
            }
        while(he<tl)//<
        {
            int k=q[++he];
            for(int i=0;i<26;i++)
                if(c[k][i])
                {
                    q[++tl]=c[k][i];
                    int nw=fail[k];
                    while(!c[nw][i]&&nw!=1)
                        nw=fail[nw];
                    if(!c[nw][i]) fail[c[k][i]]=1;
                    else fail[c[k][i]]=c[nw][i];
                }
        }
    }
    void solve()
    {
        int nw=1;
        for(int i=1,d,cr;i<=len;i++)//只走一遍前缀
        {
            d=ch[i]-'a';
            while(!c[nw][d]&&nw!=1) nw=fail[nw];
            nw=c[nw][d]; if(!nw) nw=1;
    
            cr=nw;
            while(cr!=1&&ed[cr])//遍历该前缀的每个后缀
            {
                ans+=ed[cr];ed[cr]=0;cr=fail[cr];
            }
        }
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            init();
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
            {
                scanf("%s",ch+1); len=strlen(ch+1);
                insert();
            }
            gtfl();
            scanf("%s",ch+1); len=strlen(ch+1);
            solve();
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    对scott中emp表进行各种操作
    可兼容的事件绑定方法
    深度复制
    原型链的继承
    如何在github上发布自己的项目
    用单例连接oracle数据库
    Struts2之输入验证
    JSP之监听器Listener(二)
    JSP之监听器Listener(一)————————ServletContextListener
    JSP之过滤器Filter
  • 原文地址:https://www.cnblogs.com/Narh/p/9693048.html
Copyright © 2011-2022 走看看