Hdu 2222(AC 自动机)

AC自动机就是在字典树上的KMP, 讲解的话百度就好了,讲的都挺详细的

2222就是一个裸地AC自动机

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <queue>


using namespace std;


struct Tree{
   int next[500010][26], _end[500010], fail[500010];
   int root, L;


   int newnode( ){
       for( int i = 0; i < 26; i++ )
        next[L][i] = -1;
       _end[L++] = 0;
       return L - 1;
   }


   void init(){
      L = 0;
      root = newnode();    
   }


   void insert( char buf[] ){
       int len = strlen(buf);
       int now = root;
       for( int i = 0; i < len ; i++ ){
           if(next[now][buf[i] - 'a'] == -1)
               next[now][buf[i] - 'a'] = newnode();
             now = next[now][buf[i] - 'a'];
           }
       _end[now]++;
   }


   void build( ){
      queue<int>  Q;
      fail[root] = root;
      for( int i = 0; i < 26; i++){
          if(next[root][i] == -1)
              next[root][i]= root;
          else {
              fail[next[root][i]] = root;
              Q.push(next[root][i]);
          }
      }
      while(!Q.empty()){
          int now = Q.front();
          Q.pop();
          for( int i = 0; i < 26; i++ ){
              if(next[now][i] == -1)
                next[now][i] = next[fail[now]][i];
              else{
                  fail[next[now][i]] = next[fail[now]][i];
                  Q.push(next[now][i]);
              }
          }
      }
   }
   int query(char buf[]){
       int len = strlen(buf);
       int now = root;
       int res = 0;
       for( int i = 0; i < len; i++ ){
           now = next[now][buf[i] - 'a'];
           int temp = now;
           while(temp != root){
               res += _end[temp];
               _end[temp] = 0;
               temp = fail[temp];
           }
       }
       return res;
   }


   void debug(){
       for( int i = 0; i < L; i++ ){
           printf("id = %3d, fail = %3d, end = %3d chi = [", i, fail[i], _end[i]);
           for( int j = 0; j < 26; j++ )
               printf("%2d",next[i][j]);
           printf("]\n");
       }
   }
};


char buf[1000010];
Tree ac;
int main(){


    int T, n;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        ac.init();
        for( int i = 0; i < n; i++){
            scanf("%s",&buf);
            ac.insert(buf);
        } 
        ac.build();
        scanf("%s",&buf);
        printf("%d\n",ac.query(buf));
    }
   return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值