1. 程式人生 > >專題訓練之AC自動機

專題訓練之AC自動機

amp can 字典 模板 front 單詞 cstring .net OS

推薦博客:http://www.cnblogs.com/kuangbin/p/3164106.html AC自動機小結

https://blog.csdn.net/creatorx/article/details/71100840 AC自動機最詳細的解釋

1.(HDOJ2222)http://acm.hdu.edu.cn/showproblem.php?pid=2222

題意:求目標串中出現了幾個模式串。

分析:AC自動機模板題

技術分享圖片
  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5
#include<queue> 6 using namespace std; 7 const int maxn=500010; 8 9 struct Trie 10 { 11 int nxt[maxn][26],fail[maxn],end[maxn]; //nxt為字典樹, fail相當於kmp中的nxt數組, end對單詞結尾做標記 12 int root,L; //L相當於字典樹中的sz ,root為根節點(即;0) 13 int newnode() //初相當於始化一個字典樹上的節點 14 { 15 for ( int
i=0;i<26;i++ ) nxt[L][i]=-1; 16 end[L++]=0; 17 return L-1; 18 } 19 void init() 20 { 21 L=0; 22 root=newnode(); 23 } 24 void insert(char buf[]) //大致於字典樹插入過程相同 25 { 26 int len=strlen(buf); 27 int now=root; 28 for
( int i=0;i<len;i++ ) 29 { 30 int x=buf[i]-a; 31 if ( nxt[now][x]==-1 ) nxt[now][x]=newnode(); 32 now=nxt[now][x]; 33 } 34 end[now]++; //在單詞結尾處做標記 35 } 36 void build() //相當於kmp的操作 37 { 38 queue<int>que; 39 fail[root]=root; //根節點初始化為0(即其本身) 40 for (int i=0;i<26;i++ ) 41 { 42 if ( nxt[root][i]==-1 ) nxt[root][i]=root; 43 else //Trie中已經構建的節點 44 { 45 int x=nxt[root][i]; 46 fail[x]=root; 47 que.push(x); 48 } 49 } 50 while ( !que.empty() ) 51 { 52 int now=que.front(); 53 que.pop(); 54 for ( int i=0;i<26;i++ ) 55 { 56 if ( nxt[now][i]==-1 ) //無後繼點 57 nxt[now][i]=nxt[fail[now]][i];//類似於kmp中求nxt數組一樣 58 else //存在下一個節點 59 { 60 int x=nxt[now][i]; 61 fail[x]=nxt[fail[now]][i];//失配指針指向他父節點的失配指針的下一個相同字符處 62 que.push(x); 63 } 64 } 65 } 66 } 67 int query(char buf[]) //相當於字典樹中的訪問操作 68 { 69 int len=strlen(buf); 70 int now=root; 71 int res=0; 72 for ( int i=0;i<len;i++ ) 73 //沿著整個文本串移動,每移動到一個字符(節點) 時,通過失配指針不斷找尋模式串 ,重點為源頭,找到一個就將其標記清除 74 { 75 now=nxt[now][buf[i]-a]; 76 int tmp=now; 77 while ( tmp!=root ) 78 { 79 res+=end[tmp]; 80 end[tmp]=0; 81 tmp=fail[tmp]; 82 } 83 } 84 return res; //返回單詞個數 85 } 86 void debug() 87 { 88 for ( int i=0;i<L;i++ ) 89 { 90 printf("%id=%3d,fail=%3d,end=%3d,chi=[",i,fail[i],end[i]); 91 for ( int j=0;j<26;j++ ) printf("%2d",nxt[i][j]); 92 printf("]\n"); 93 } 94 } 95 }; 96 char buf[maxn*2]; 97 Trie ac; 98 int main() 99 { 100 int T,n; 101 scanf("%d",&T); 102 while ( T-- ) 103 { 104 scanf("%d",&n); 105 ac.init(); 106 for ( int i=0;i<n;i++ ) 107 { 108 scanf("%s",buf); 109 ac.insert(buf); 110 } 111 ac.build(); 112 scanf("%s",buf); 113 printf("%d\n",ac.query(buf)); 114 } 115 return 0; 116 }
AC自動機模板(含解釋) 技術分享圖片
  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<queue>
  6 using namespace std;
  7 const int maxn=500010;
  8 
  9 struct Trie
 10 {
 11     int nxt[maxn][26],fail[maxn],end[maxn]; 
 12     int root,L;   
 13     int newnode()  
 14     {
 15         for ( int i=0;i<26;i++ ) nxt[L][i]=-1;
 16         end[L++]=0;
 17         return L-1;
 18     }
 19     void init()
 20     {
 21         L=0;
 22         root=newnode();
 23         memset(end,0,sizeof(end));
 24     }
 25     void insert(char buf[]) 
 26     {
 27         int len=strlen(buf);
 28         int now=root;
 29         for ( int i=0;i<len;i++ )
 30         {
 31             int x=buf[i]-a;
 32             if ( nxt[now][x]==-1 ) nxt[now][x]=newnode();
 33             now=nxt[now][x];
 34         }
 35         end[now]++; 
 36     }
 37     void build()   
 38     {
 39         queue<int>que;
 40         fail[root]=root; 
 41         for (int i=0;i<26;i++ )
 42         {
 43             if ( nxt[root][i]==-1 ) nxt[root][i]=root;
 44             else 
 45             {
 46                 int x=nxt[root][i];
 47                 fail[x]=root;
 48                 que.push(x);
 49             }
 50         }
 51         while ( !que.empty() )
 52         {
 53             int now=que.front();
 54             que.pop();
 55             for ( int i=0;i<26;i++ )
 56             {
 57                 if ( nxt[now][i]==-1 ) 
 58                     nxt[now][i]=nxt[fail[now]][i];
 59                 else 
 60                 {
 61                     int x=nxt[now][i];
 62                     fail[x]=nxt[fail[now]][i];
 63                     que.push(x);
 64                 }
 65             }
 66         }
 67     }
 68     int query(char buf[]) 
 69     {
 70         int len=strlen(buf);
 71         int now=root;
 72         int res=0;
 73         for ( int i=0;i<len;i++ ) 
 74         {
 75             now=nxt[now][buf[i]-a];
 76             int tmp=now;
 77             while ( tmp!=root )
 78             {
 79                 res+=end[tmp];
 80                 end[tmp]=0;
 81                 tmp=fail[tmp];
 82             }
 83         }
 84         return res; 
 85     }
 86     void debug()
 87     {
 88         for ( int i=0;i<L;i++ )
 89         {
 90             printf("%id=%3d,fail=%3d,end=%3d,chi=[",i,fail[i],end[i]);
 91             for ( int j=0;j<26;j++ ) printf("%2d",nxt[i][j]);
 92             printf("]\n");
 93         }
 94     }
 95 };
 96 char buf[maxn*2];
 97 Trie ac;
 98 int main()
 99 {
100     int T,n;
101     scanf("%d",&T);
102     while ( T-- )
103     {
104         scanf("%d",&n);
105         ac.init();
106         for ( int i=0;i<n;i++ )
107         {
108             scanf("%s",buf);
109             ac.insert(buf);
110         }
111         ac.build();
112         scanf("%s",buf);
113         printf("%d\n",ac.query(buf));
114     }
115     return 0;
116 }
HDOJ2222

專題訓練之AC自動機