hdu2896 ac自动机

来源:互联网 发布:玄彬韩国地位知乎 编辑:程序博客网 时间:2024/06/07 10:36

给定几个模式串,看是否出现在主串中。

用所给的模式串构建AC自动机,然后用主串去匹配。

每个模式串的末尾记录该串的标号,而中间的字符的标号为0即可,最后跑一次AC自动机就行了。

3
aaa
bbb
ccc
2
aaabbbccc
bbaacc
 


Sample Output
web 1: 1 2 3
total: 1

const  int  maxn = 1000008  ;struct TrieNode{       TrieNode *fail ;       TrieNode *next[130] ;       int id ;       TrieNode(){           fail = NULL ;           id = 0 ;           for(int i = 0 ; i < 130 ; i++) next[i] = NULL ;       }};void  Insert(TrieNode *root , char *s , int id){      TrieNode *now = root  ;      while(*s){          int k = *s - ' ' ;          if(now->next[k] == NULL)               now->next[k] = new TrieNode() ;          now = now->next[k] ;          s++ ;      }      now->id = id ;}TrieNode *que[maxn] ;void makeAC(TrieNode *root){     int head = 0 , tail = -1 ;     que[++tail] = root ;     while(head <= tail){          TrieNode *now = que[head++] ;          for(int i = 0 ; i < 130 ; i++){              if(now->next[i] != NULL){                  if(now == root)                      now->next[i]->fail = root ;                  else{                      TrieNode *f = now->fail ;                      while(f != NULL){                          if(f->next[i] != NULL){                              now->next[i]->fail = f->next[i] ;                              break ;                          }                          f = f->fail ;                      }                      if(f == NULL)                          now->next[i]->fail = root ;                  }                  que[++tail] = now->next[i] ;              }          }     }}int  vis[508] ;int  ask(TrieNode *root , char *s){     memset(vis , 0 , sizeof(vis)) ;     TrieNode *now = root ;     int sum = 0 , k ;     while(*s){          k = *s - ' ' ;          while(now != root && now->next[k] == NULL)            now = now->fail ;          now = now->next[k] ;          if(now == NULL) now = root ;          TrieNode *f = now ;          while(f != root){               vis[f->id] = 1 ;               if(f->id > 0) sum++ ;               f = f->fail ;          }          s++ ;     }     return sum ;}char word[208] ;char text[10008] ;int  main(){     int n , m  , i , j , total  ;     while(cin>>n){          TrieNode *root = new TrieNode() ;          for(i = 1 ; i <= n ; i++){              scanf("%s" , word) ;              Insert(root , word , i) ;          }          total = 0 ;          makeAC(root) ;          cin>>m ;          for(i = 1 ; i <= m ; i++){               scanf("%s" , text) ;               if(ask(root , text) > 0){                   total++ ;                   printf("web %d:" , i) ;                   for(j = 1 ; j <= n ; j++){                      if(vis[j]) printf(" %d" , j) ;                   }                   puts("") ;               }          }          printf("total: %d\n" ,total) ;     }     return 0 ;}


/*AC-------------*/const  int maxn = 500*208 ;const  int kind = 128 ;int    next[maxn][kind] ;int    fail[maxn] ;int    id[maxn]   ;struct  AC{        int  root , n ;        int  newnode(){             id[n] = 0 ;             for(int i = 0 ; i < kind ; i++) next[n][i] = -1 ;             return n++ ;        }        void  Init(){              n = 0 ;              root = newnode() ;        }        void  Insert(char *s , int idx){              int now = root  , k ;              while(*s){                   k = *s - ' ' ;                   if(next[now][k] == -1)                       next[now][k] = newnode() ;                   now = next[now][k] ;                   s++ ;              }              id[now] = idx  ;        }        void  makeAc(){              queue<int> q ;              fail[root] = root ;              int now , i ;              for(i = 0 ; i < kind ; i++){                   if(next[root][i] == -1)                       next[root][i] = root ;                   else{                       fail[next[root][i]] =  root ;                       q.push(next[root][i]) ;                   }              }              while(! q.empty()){                   now = q.front() ; q.pop() ;                   for(i = 0 ; i < kind ; 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]) ;                       }                   }              }        }        bool vis[508] ;        int  ask(char *s , int m , int idx){             memset(vis , 0 , sizeof(vis)) ;             int now = root , k  ;             while(*s){                  k = *s - ' ' ;                  now = next[now][k] ;                  int t = now  ;                  while(t != root){                       vis[id[t]] = 1 ;                       t = fail[t] ;                  }                  s++ ;             }             vector<int> lis ;  lis.clear() ;             for(int i = 1 ; i <= m ; i++){                  if(vis[i]) lis.push_back(i) ;             }             if(lis.size() == 0) return 0 ;             else{                 printf("web %d:" , idx) ;                 for(int i = 0 ; i < lis.size() ; i++) printf(" %d" , lis[i]) ;                 puts("") ;                 return 1 ;             }        }}ac ;/*EndAc---------------*/char  word[208] ;char  text[10008] ;int   main(){      int t , n  , i  , sum  , m ;      while(cin>>n){           ac.Init() ;           for(i = 1 ; i <= n ; i++){                scanf("%s" , word) ;                ac.Insert(word , i) ;           }           ac.makeAc() ;           sum = 0 ;           cin>>m ;           for(i = 1 ; i <= m ; i++){                scanf("%s" , text) ;                sum += ac.ask(text , n , i) ;           }           printf("total: %d\n" , sum) ;      }      return 0 ;}






0 0
原创粉丝点击