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

    这个题网上有很多讲解,感觉在看这个题之前最好先去看看KMP ,不然看再多的讲解,可能也不能理解构造失败指针的意义是什么。在KMP中NEXT的作用是党不匹配时指针后移,而这个后移量则是通过 NEXT 来控制的,这个题里面 构造 失败指针的意义 和NEXT的作用一样,就是前后移动指针的。这个懂了,再看看别人的图示,就会明白构造的过程,其中 我理解的是用 广度优先 遍历的。大家可以看看这个文章http://www.cppblog.com/mythit/archive/2009/04/21/80633.html 里面讲解的很详细。

    代码:

    #include<stdio.h>
    #include<queue>
    using namespace std;
    typedef struct node
    {
        int count;
        node *fail;
        node *next[26];
    }node;
    node *h;
    void insert(char *key)
    {
        int i;
        node *p;
        char *q;
        p=h;
        q=key;
        while(*q)
        {
            if(p->next[*q-'a']==NULL)
            {
                p->next[*q-'a']=(node*)malloc(sizeof(node));
                p->next[*q-'a']->count=0;
                p->next[*q-'a']->fail=NULL;
                for(i=0;i<26;++i)
                    p->next[*q-'a']->next[i]=NULL;
            }
            p=p->next[*q-'a'];
            q++;
        }
        p->count++;
    }
    void makefail()
    {
        int i;
        node *fa,*so,*an;
        queue<node*>qu;
        qu.push(h);
        while(!qu.empty())
        {
            fa=qu.front();
            qu.pop();
            for(i=0;i<26;++i)
                if(fa->next[i]!=NULL)
                {
                    if(fa==h)
                        fa->next[i]->fail=h;
                    else
                    {
                        so=fa->next[i];
                        an=fa->fail;
                        while(an!=NULL&&an->next[i]==NULL)
                            an=an->fail;
                        if(an==NULL)
                            so->fail=h;
                        else
                            so->fail=an->next[i];
                    }
                    qu.push(fa->next[i]);
                }
        }
    }
    int find(char *des)
    {
        int sum=0,at,i;
        node *p,*q;
        p=h;
        i=0;
        while(des[i])
        {
            at=des[i]-'a';
            while(p->next[at]==NULL&&p!=h)
                p=p->fail;
            p=p->next[at];
            if(p==NULL)
                p=h;
            q=p;
            while(q!=h&&q->count)
            {
                sum+=q->count;
                q->count=0;
                q=q->fail;
            }
            i++;
        }
        return sum;
    }
    int main()
    {
        int T,i,n;
        char str[55],des[1000005];
        h=(node*)malloc(sizeof(node));
        scanf("%d",&T);
        while(T--)
        {
            h->fail=NULL;
            for(i=0;i<26;++i)
                h->next[i]=NULL;
            scanf("%d",&n);
            while(n--)
            {
                scanf("%s",str);
                insert(str);
            }
            makefail();
            scanf("%s",des);
            printf("%d\n",find(des));
        }
        return 0;
    }
  • 相关阅读:
    bugku insertsql
    PHP 审计
    文件上传漏洞学习 6-10
    ssh 使用密钥无法登入Linux系统
    Linux 服务器上安装Webmin
    Aircrack-ng无线破解总结
    linux网络流量实时监控工具之iptraf 【个人比较喜欢用的流量监控软件】
    Linux下mysql的root密码忘记解决方法
    C指针 【温故】
    Nginx+keepalive 负载均衡
  • 原文地址:https://www.cnblogs.com/zibuyu/p/2643558.html
Copyright © 2011-2022 走看看