• hdu 2222(AC自动机第一题)


    题意:首先输入n个单词,然后输入一个字符串,题目要求的事在传中可以找到几个开始输入的单词。

    分析:这是我做的第一个AC自动机模板题,对于刚开始学习AC自动机的人我推荐两个资料:第一个:file:///C:/Users/Administrator/AppData/Local/Temp/360zip$Temp/360$0/AC自动机算法详解%20-%20极限定律%20-%20C++博客.mht

    第二个资料:这个我觉得也挺好的,http://www.cnblogs.com/zhuangli/archive/2008/08/13/1267249.html

    看完这两个资料之后这道题就不是问题了!

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    struct node{
        int count;
        struct node *fail;
        struct node *next[26];
        node()
        {
            fail=NULL;
            memset(next,NULL,sizeof(next));
            count=0;
        }
    }*queue[500005];
    struct node *root;
    char keyword[55],str[1000005];
    void build(char *str)//建立字典树
    {
         struct node *p=p=root;
         int index;
         for(;*str!='\0';str++)
         {
             index=*str-'a';
             if(p->next[index]==NULL)
                 p->next[index]=new node;
             p=p->next[index];
         }
         p->count++;
    }
    void AC_tree()//构造失败指针
    {
         int f,r,i;
         struct node *p,*temp;
         root->fail=NULL;
         f=0;r=0;
         queue[r++]=root;
         while(f!=r)
         {
            p=queue[f++];
            for(i=0;i<26;i++)
            {
               if(p->next[i]!=NULL)
               {
                   temp=p->fail;
                   while(temp!=NULL)
                   {
                      if(temp->next[i]!=NULL)
                      {
                          p->next[i]->fail=temp->next[i];
                          break;
                      }
                      temp=temp->fail;
                   }
                   if(temp==NULL)
                       p->next[i]->fail=root;
                   queue[r++]=p->next[i];
               }
            }
         }
    }
    int find(char *str)//单词查找
    {
         int index;
         int sum=0;
         struct node *p,*temp;
         p=root;
         for(;*str!='\0';str++)
         {
             index=*str-'a';
             while(p->next[index]==NULL&&p!=root)
                 p=p->fail;
             p=p->next[index];
             if(p==NULL)
                 p=root;
             temp=p;
             while(temp!=root&&temp->count!=-1)
             {
                sum=sum+temp->count;
                temp->count=-1;
                temp=temp->fail;
             }
         }
         return sum;
    }
    void del(struct node *root)
    {
       int i;
       for(i=0;i<26;i++)
       {
           if(root->next[i]!=NULL)
               del(root->next[i]);
       }
       delete(root);
    }
    int main()
    {
        int T,n;
        while(scanf("%d",&T)!=EOF)
        {
            while(T--)
            {
                root=new node;
                scanf("%d",&n);
                getchar();
                while(n--)
                {
                    scanf("%s",keyword);
                    build(keyword);
                }
                AC_tree();
                scanf("%s",str);
                printf("%d\n",find(str));
                del(root);
            }
        }
        return 0;
    }

     用静态数组模拟:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<iostream>
    #include<queue>
    using namespace std;
    struct node{
        int next[26];
        int fail;
        int count;
        void init()
        {
            memset(next,0,sizeof(next));
            fail=0;
            count=0;
        }
    };
    struct node a[500005];
    int n,tot;
    char keyword[55];
    char S[1000005];

    void chushihua()
    {
        tot=0;
        a[0].init();
    }

    void insert(char *str)
    {
         int index,p;
         p=0;
         for(;*str!='\0';str++)
         {
             index=*str-'a';
             if(a[p].next[index]==0)
             {
                 a[++tot].init();
                 a[p].next[index]=tot;
             }
             p=a[p].next[index];
         }
         a[p].count++;
    }

    void build_fail()
    {
         int i,p,son,cur;
         queue<int>Q;
         Q.push(0);
         while(!Q.empty())
         {
             p=Q.front();
             Q.pop();
             for(i=0;i<26;i++)
             {
                   if(a[p].next[i]!=0)
                   {
                        son=a[p].next[i];
                        cur=a[p].fail;
                        if(p==0)
                           a[son].fail=0;
                        else
                        {
                           while(cur!=0&&a[cur].next[i]==0)
                               cur=a[cur].fail;
                           a[son].fail=a[cur].next[i];
                        }
                        Q.push(son);
                   }
             }
         }
    }

    int solve()
    {
        int i,index,p=0,temp,res;
        res=0;
        for(i=0;S[i]!='\0';i++)
        {
             index=S[i]-'a';
             while(p!=0&&a[p].next[index]==0)
                p=a[p].fail;
             if(a[p].next[index]!=0)
                 p=a[p].next[index];
             temp=p;
             while(temp&&a[temp].count!=-1)
             {
                 res=res+a[temp].count;
                 a[temp].count=-1;
                 temp=a[temp].fail;
             }
        }
        return res;
    }
    int main()
    {
        int T;
        while(scanf("%d",&T)!=EOF)
        {
            while(T--)
            {
                chushihua();
                  scanf("%d",&n);
                getchar();
                while(n--)
                {
                   scanf("%s",keyword);
                   insert(keyword);
                }
                build_fail();
                scanf("%s",S);
                printf("%d\n",solve());
            }
        }
        return 0;
    }

  • 相关阅读:
    优秀的 Java 项目,代码都是如何分层的?
    计算机应届生月薪大多是多少?
    零基础要怎么学JAVA?
    自学 Java 怎么入门?
    Java学习路线总结,已Get腾讯Offer
    java培训出来的如何找工作?
    离散数学学习笔记
    一些公式
    一个模拟
    秦皇岛wannafly[数论]学习笔记
  • 原文地址:https://www.cnblogs.com/jiangjing/p/3036701.html
Copyright © 2020-2023  润新知