soj3690 Keywords Search AC自動機

這道是個典型的AC自動機。

在trie的基礎上添加fail指針,指向類似於KMP的next處。

大意是求一段文字中出現過多少某字典的詞。

主要用於多串匹配。

  1. #include <stdio.h>  
  2. #include <ctype.h>  
  3. #include <string.h>  
  4. #include <queue>  
  5.  
  6. using namespace std;  
  7.  
  8. #define show(array,n) for( i = 0 ; i < n ; i++) printf("%d ",array[i]) ; puts("");   
  9. #define REP(i,st,n) for( i = st ; i < n ; i++)  
  10. #define ss(str) scanf("%s",str)  
  11.  
  12. struct node {  
  13.     node *next[26] , *fail ;  
  14.     int leaf ;  
  15.     node():leaf(0),fail(0)    {    memset(next,0,sizeof(next));    }  
  16. };  
  17.  
  18. const int maxlen = 1000001 ;  
  19. const int maxn = 10001 ;  
  20. char diary[maxlen] ;  
  21. node *root ;  
  22.  
  23. inline void init_trie()    {      
  24.     root = new node();  
  25. }  
  26.  
  27. inline void insert(char str[]) {  
  28.     node* ptr = root ;  
  29.     forint i = 0 ; str[i] ; i++) {  
  30.         if( ptr->next[str[i]-'a'] == NULL )    ptr->next[str[i]-'a'] = new node();  
  31.         ptr = ptr->next[str[i]-'a'] ;  
  32.     }  
  33.     ptr->leaf++;  
  34. }  
  35.  
  36. inline void build_ac_machine() {  
  37.     queue<node*> q ;  
  38.     q.push(root);  
  39.     while(!q.empty())  
  40.     {  
  41.         node* ptr = q.front();    q.pop();  
  42.         forint i = 0 ; i < 26 ; i++) if( ptr->next[i] != NULL ) {  
  43.             // cal ptr->next[i]'s fail  
  44.             node* temp = ptr->fail ;  
  45.             while( temp != NULL && temp->next[i] == NULL ) temp = temp->fail ;  
  46.             if( temp == NULL ) ptr->next[i]->fail = root ;  
  47.             else ptr->next[i]->fail = temp->next[i] ;  
  48.             q.push(ptr->next[i]);  
  49.         }  
  50.     }  
  51. }  
  52.  
  53. inline int match(char str[])  
  54. {  
  55.     int ans , i , j , k ;  
  56.     node* ptr = root ;  
  57.     //i = strlen(str) ; str[i++] = '$';  str[i] = 0 ;  
  58.     for( i = ans = 0 ; str[i] ; i++) {          
  59.         j = str[i] - 'a' ;  
  60.         while( ptr!=root && ptr->next[j] == NULL ) ptr = ptr->fail ;  
  61.         ptr = ptr->next[j] ;  
  62.         if( ptr == NULL ) ptr = root ;  
  63.         node* temp = ptr ;  
  64.         while(temp!=NULL&&temp->leaf>=0) {      
  65.             ans += temp->leaf ;  
  66.             temp->leaf = -1 ;    //-1,代表之後的fail都取過了,所以速度較快  
  67.             temp = temp->fail ;  
  68.         }  
  69.     }  
  70.     return ans ;  
  71. }  
  72.  
  73. int main() {  
  74.     char str[64] ;  
  75.     int i , t , n ;  
  76.     scanf("%d",&t);  
  77.     while(t--)  
  78.     {  
  79.         scanf("%d",&n);  
  80.         init_trie();  
  81.         REP(i,0,n)      
  82.         {  
  83.             ss(str);  
  84.             insert(str);  
  85.         }  
  86.         build_ac_machine();  
  87.         ss(diary);          
  88.         printf("%d\n",match(diary));  
  89.     }  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章