AC自动机

来源:互联网 发布:淘宝卖户外是正品吗 编辑:程序博客网 时间:2024/06/03 22:41

这里有一篇很好的文章---AC自动机详解

简要介绍一下AC自动机原理:

提前你应掌握的知识:

1、字典树---Trie-Tree

2、自动机一些简单入门级概念,如(状态)

3、KMP算法的next数组的生成原理

原理如下:

1、首先由模式串构建一颗字典树 2、根据KMP中next数组的原理,构建字典树Fail指针的前缀 3、输入主串,搜索


看了以后一下是我的详细代码:
[cpp] view plaincopyprint?
  1. <pre class="cpp" name="code">//////////////////////////////////////////////////////////////////////////
  2. //                       AC自动机模板 
  3. //                       Author:chenzulong
  4. //                       Date: 2012年3月10日
  5. //////////////////////////////////////////////////////////////////////////
  6.  
  7. #include<iostream>
  8. #include<algorithm> 
  9. #include<functional>
  10. #include<queue> 
  11. #include<string> 
  12. #include<cstring> 
  13. #include<exception>
  14. #include<typeinfo> 
  15. #include<iterator>
  16.  
  17. #ifndef AC_AUTOMAT
  18. #define AC_AUTOMAT 
  19.  
  20. class ACtomat{ 
  21.      
  22.     //some interfaces 
  23.     public
  24.          
  25.         ACtomat(){ 
  26.              
  27.         } 
  28.          
  29.         ~ACtomat(){ 
  30.  
  31.             delete root;
  32.         } 
  33.  
  34.         //initiliation the actomat 
  35.         bool ActomatInit(){
  36.              
  37.             try
  38.                  
  39.                 index = 0; 
  40.                 root = &Table[index]; 
  41.                 memset(Table[0].next,0,sizeof(Table[0].next));
  42.                 Table[0].cnt = 0; 
  43.                 Table[0].prefix = NULL; 
  44.                  
  45.             }catch(...){
  46.                  
  47.                 std::cerr<<"Unknow Erro happen"<<std::endl;
  48.                 return false;
  49.             } 
  50.             return true;
  51.         } 
  52.          
  53.         //input the str-pattern ,then conostruct the trie-tree
  54.         bool insert(const std::string& str){
  55.              
  56.             Trie* r = root; 
  57.             std::string::const_iterator iter = str.begin();
  58.              
  59.             try
  60.                  
  61.                 while(iter!=str.end()){
  62.                      
  63.                     int t = *iter -'a'
  64.                      
  65.                     if(!r->next[t]){
  66.                          
  67.                         index++; 
  68.                         memset(Table[index].next,0,sizeof(Table[index].next));
  69.                         Table[index].prefix = NULL; 
  70.                         Table[index].cnt = 0; 
  71.                         r->next[t] = &Table[index]; 
  72.                     } 
  73.                      
  74.                     r = r->next[t]; 
  75.                     iter++; 
  76.                 } 
  77.                  
  78.                 r->cnt++; 
  79.             }catch(...){
  80.                  
  81.                 std::cerr<<"Unknow Error happen"<<std::endl;
  82.                 delete r; 
  83.                 r= 0; 
  84.                 return false;
  85.             } 
  86.              
  87.             //constructor the fail-pointer
  88.             if(ACtomatInitPrefix()){
  89.                  
  90.                 return true;
  91.             }else
  92.                  
  93.                 return false
  94.             } 
  95.         } 
  96.          
  97.         //run the actomat
  98.         bool ACtomatRun(const std::string& str,int& ans){
  99.              
  100.             Trie* p = root; 
  101.             Trie* tp = NULL; 
  102.  
  103.             ans = 0; 
  104.              
  105.             std::string::const_iterator iter = str.begin();
  106.              
  107.             try
  108.                  
  109.                 while(iter!=str.end()){
  110.                      
  111.                     int t = *iter -'a'
  112.                      
  113.                     //recurisive
  114.                     while(!p->next[t]&&p!=root){
  115.                          
  116.                         p = p ->prefix; 
  117.                          
  118.                     } 
  119.                      
  120.                     p = p->next[t]; 
  121.                      
  122.                     if(!p){ 
  123.                          
  124.                         p = root; 
  125.                     } 
  126.                      
  127.                     tp = p; 
  128.                      
  129.                     //go on matching,continue...
  130.                     while(tp!=root&&tp->cnt!=-1){
  131.                          
  132.                         ans +=tp->cnt; 
  133.                         tp->cnt = -1; 
  134.                         tp = tp->prefix; 
  135.                     } 
  136.                      
  137.                     iter++; 
  138.                 } 
  139.             }catch(...){
  140.                  
  141.                 std::cerr<<"Unknow Error happend"<<std::endl;
  142.                 delete p; 
  143.                 delete tp;
  144.                 return false;
  145.             }    
  146.             return true;
  147.         } 
  148.          
  149.          
  150.     //some constant variables    
  151.     private
  152.          
  153.         enum
  154.             MAXN_WORD=1000001, 
  155.                 MAXN_TOTAL = 500000 
  156.         }; 
  157.          
  158.         struct Trie{ 
  159.              
  160.             enum
  161.                 MAXNT_NODE = 26 
  162.             }; 
  163.  
  164.             int cnt; 
  165.             Trie* next[MAXNT_NODE]; 
  166.             Trie* prefix; 
  167.         }; 
  168.  
  169.     //some private variable
  170.     private
  171.              
  172.             Trie* root; 
  173.             Trie Table[MAXN_TOTAL];  
  174.             int index; 
  175.     //some functions whichs are used in class      
  176.     private
  177.              
  178.         //get the fail-pointer table
  179.             bool ACtomatInitPrefix(){
  180.                  
  181.                 Trie* r,*tmp,*father; 
  182.                 try
  183.                      
  184.                     r = root; 
  185.                     std::queue<Trie*> q; 
  186.                      
  187.                     q.push(root); 
  188.                     root->prefix = NULL; 
  189.                      
  190.                     while(!q.empty()){
  191.                          
  192.                         father = q.front(); 
  193.                          
  194.                         q.pop(); 
  195.                          
  196.                         for(int i=0;i<26;i++){
  197.                              
  198.                             if(father->next[i]){
  199.                                  
  200.                                 tmp = father->prefix; 
  201.                                 while(tmp&&!tmp->next[i]){
  202.                                      
  203.                                     tmp = tmp->prefix; 
  204.                                 } 
  205.                                  
  206.                                 if(!tmp){
  207.                                      
  208.                                     father->next[i]->prefix = root; 
  209.                                 }else{
  210.                                      
  211.                                     father->next[i]->prefix = tmp->next[i];
  212.                                 } 
  213.                                  
  214.                                 q.push(father->next[i]); 
  215.                             } 
  216.                         } 
  217.                     } 
  218.                 }catch(...){ 
  219.                      
  220.                     std::cerr<<"Unkonw Error happen"<<std::endl;
  221.                     delete father;
  222.                     delete r; 
  223.                     returnfalse
  224.                 } 
  225.  
  226.                 //delete father; 
  227.                 //delete r;
  228.                 return true;
  229.             } 
  230. }; 
  231. #endif 
  232.  
  233. int main(){ 
  234.      
  235.     int nCase; 
  236.     int num; 
  237.     std::string str; 
  238.      
  239.     std::cin>>nCase; 
  240.     ACtomat* acMachine = new ACtomat;
  241.     while(nCase--){ 
  242.          
  243.         std::cin>>num; 
  244.          
  245.         acMachine->ActomatInit(); 
  246.         while(num--){ 
  247.             std::cin>>str; 
  248.             acMachine->insert(str); 
  249.         } 
  250.  
  251.         std::cin>>str; 
  252.         int ans ; 
  253.         acMachine->ACtomatRun(str,ans); 
  254.         std::cout<<ans<<std::endl; 
  255.          
  256.     } 
  257.     return 0; 
  258.  
  259. </pre><br> 
  260. <br> 
  261. <pre></pre> 
  262. <p></p> 
  263. <pre></pre> 
  264. <p></p> 
  265. <pre></pre> 
  266. <pre></pre> 
  267. <pre></pre> 
  268. <pre></pre> 
0 0
原创粉丝点击