HDOJ 2222 Keywords Search

        赤裸裸的AC自动机模版题。ac自动机以后再补上,先贴代码把:

代码:

#include<iostream>
#include<string.h>
using namespace std;
struct node
{
       node*fail;  //失败指针
       node*next[26];
       int cnt;
       node(){
              fail=NULL;
              for( int i =0; i<26; i++)
                   next[i]=NULL;
              cnt=0;
       }            
}* q[500001];
char keyword[51];
char str[1000001];
int first,rear;
void Creat_Trie(char* strg,node*root)  //构造字典树 
{
     int i,id,len;
     node *p=root;
     len=strlen(strg);
     for( i=0; i<len; i++){
          id=strg[i]-'a';
          if( p->next[id]==NULL)
              p->next[id]=new node();
          p=p->next[id];
     } 
     p->cnt++;
     //最后一个结点加1,代表以这个字母结尾的单词有几个。 
}

void Build_ac_automation(node *root) //广度遍历建立fail指针 
{
     int i;
     root->fail=NULL;
     q[rear++]=root;
     while( first!=rear){
            node *temp=q[first++];
            node *p=NULL;
            for( i=0; i<26; i++){
                 if( temp->next[i]!=NULL){
                     if( temp==root)
                         temp->next[i]->fail=root;
                     else{
                          p=temp->fail;
                          while( p!=NULL){
                                 if( p->next[i]!=NULL){
                                     temp->next[i]->fail=p->next[i];
                                     break;
                                 }
                                 p=p->fail;
                          }
                          if( p==NULL) 
                              temp->next[i]->fail=root;
                     }
                     q[rear++]=temp->next[i];
                 }
            }
     }       
}

int Query(node *root) //查询单词 
{
    int i,id,ret,len;
    len=strlen(str);
    node*p=root;
    ret=0;
    for( i=0; i<len; i++){
         id=str[i]-'a';
         while( p->next[id]==NULL&&p!=root)
                p=p->fail;
         p=p->next[id];
         if( p==NULL)
             p=root;
         node *temp=p;
         while( temp!=root&&temp->cnt!=-1){
                ret+=temp->cnt;
                temp->cnt=-1;
                temp=temp->fail;
         }
    }
    return ret;    
}
int main()
{
    int t,n;
    scanf("%d",&t);
    while( t--){
           first=rear=0;
           node *root=new node();
           scanf("%d",&n); 
           getchar();
           while( n--){
                  gets(keyword);
                  Creat_Trie(keyword,root);
           }
           Build_ac_automation(root);
           scanf("%s",str);
           printf("%d\n",Query(root));
    } 
    return 0; 
}




评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值