AC 自动机 水题 hdu 3065

来源:互联网 发布:js常用正则表达式大全 编辑:程序博客网 时间:2024/05/29 03:16

AC自动机 :

AC自动机算法分为3步:构造一棵Trie树,构造失败指针和模式匹配过程。

在学习 AC 自动机 之前 , 一般应先学会 字典树 (也就是 tire树 ) 和 KMP 算法 (fail指针的构造 就是这个思想)。

用模拟指针实现的AC自动机

#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;const int maxn = 10000100;struct Node {   int num, fail;   int next[26];   void init  (){     for(int i = 0; i<=25 ; i++){        next[i] = 0;     }     fail = -1;     num = 0;   }}node [maxn];int n;char s[1010][55];int tot = 0 ;void insert(char s[]){    int cur = 0;    for(int i=0;s[i];i++){       // cout << s[i]<<" ***";       int t = s[i] - 'A' ;       if(node[cur].next[t]){          cur = node[cur].next[t];     // cout << "cur:" <<cur <<endl;       }else{         node[cur].next[t] = ++tot;     node[tot].init();     cur = tot;       }    }}void get_fail (){  queue<int > Q;  Q.push(0);  while(!Q.empty()){      int now = Q.front();      Q.pop();      for(int i= 0;i<26;i++){          if(node[now].next[i]){//          cout <<"haha"<<endl;           int p = node[now].fail ;           int q = node[now].next[i];              while(p!=-1&& !node[p].next[i]){            p = node[p].fail;          }          if(p == -1 ) node[q].fail  = 0;              else { node[q].fail = node[p].next[i];//            cout <<q<<"fail "<< node[q].fail<<endl;          }          Q.push(q);      }      }  }}void match (char s[]){    int len = strlen(s);    int rt = 0 ;    int p,ans;    for(int i=0 ;i < len ; i++){//        cout << s[i]<<"&&&& ";       int t = s[i]-'A';      if(t>25||t<0){        rt = 0 ;    continue;      }      p = rt ;      while(p!=-1&& !node[p].next[t]){         p = node[p].fail;      }      if(p==-1) rt = 0 ;      else rt = node[p].next[t];      node[rt].num ++ ;   //   cout <<rt << "rt"<<endl;    }}int query(char s[]){    int p= 0 , rt= 0 ;    for(int i= 0 ;s[i];i++){         int t = s[i] - 'A';     if(node[p].next[t]){         p = node[p].next[t];     }else{      return 0 ;     }    }    return node[p].num;}char  mode[2000100];int main(){   while( ~scanf("%d",&n)){  for(int i=1;i<=n;i++){     scanf("%s",s[i]);  }  node[0].init();  tot = 0;  for(int i=1;i<=n ;i++){     insert(s[i]);  }   get_fail(); // cout <<"***"<<endl;  scanf("%s",mode);  match(mode); // cout <<"**(()"<<endl;  for(int i=1;i<= n;i++){//      cout <<s[i]<<endl;      int ans = query(s[i]);  //    cout << ans <<endl;      if(ans){         cout << s[i]<<": "<<ans<<endl;      }   } } return  0;}



原创粉丝点击