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;
}

 

posted on 2013-04-22 21:52  后端bug开发工程师  阅读(554)  评论(0编辑  收藏  举报

导航