1. 程式人生 > 實用技巧 >AC自動機-hdu2222 hdu2896

AC自動機-hdu2222 hdu2896

hdu2222 題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=2222

題目大意:給定一堆模式串和一個匹配串,問匹配串中包含多少模式串

AC自動機板子中的板子題。AC自動機的前需知識是KMP和trie樹(字典樹),需要的KMP的思想就是失配之後的最優化處理。事實上,AC自動機是在trie樹上做一個失配最優化,也就是在trie樹的基礎上建立fail樹。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<queue>
 5
using namespace std; 6 7 #define maxn 1000005 8 9 int trie[maxn][26]; 10 int fail[maxn]; 11 int cntword[maxn]; 12 int cnt; 13 14 void insertWords(char s[]) 15 { 16 int root=0; 17 int len=strlen(s); 18 for(int i=0;i<len;i++) 19 { 20 int next=s[i]-'a'; 21 if(!trie[root][next]){
22 trie[root][next]=++cnt; 23 } 24 root=trie[root][next]; 25 } 26 cntword[root]++; 27 } 28 29 void getFail() 30 { 31 queue<int>q; 32 while(!q.empty()) q.pop(); 33 int now=0; 34 for(int i=0;i<26;i++){ 35 if(trie[now][i]){ 36 fail[trie[now][i]]=0
; 37 q.push(trie[now][i]); 38 } 39 } 40 while(!q.empty()){ 41 now = q.front(); 42 q.pop(); 43 for(int i=0;i<26;i++){ 44 if(trie[now][i]){ 45 fail[trie[now][i]]=trie[fail[now]][i]; 46 q.push(trie[now][i]); 47 } 48 else trie[now][i]=trie[fail[now]][i]; 49 } 50 } 51 } 52 53 int query(char s[]) 54 { 55 int ans=0,now=0,len=strlen(s); 56 for(int i=0;i<len;i++){ 57 now=trie[now][s[i]-'a']; 58 for(int j=now;j&&cntword[j]!=-1;j=fail[j]) 59 { 60 ans+=cntword[j]; 61 cntword[j]=-1; 62 } 63 } 64 return ans; 65 } 66 67 int main() 68 { 69 int n; 70 int t; 71 scanf("%d",&t); 72 char s[maxn]; 73 while(t--) 74 { 75 memset(fail,0,sizeof(fail)); 76 memset(trie,0,sizeof(trie)); 77 memset(cntword,0,sizeof(cntword)); 78 cnt=0; 79 scanf("%d",&n); 80 while(n--) 81 { 82 scanf("%s",s); 83 insertWords(s); 84 } 85 fail[0]=0; 86 getFail(); 87 scanf("%s",s); 88 printf("%d\n",query(s)); 89 } 90 return 0; 91 }
hdu2222

hdu2896 題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=2896

題目大意:給定n個模式串,m個匹配串,求每個匹配串中有哪寫模式串,所有匹配串中有多少匹配到模式串。

這題也是一道AC自動機板子題,比上面hdu2222稍有些難度,這裡我們先將模式串構建好樹,然後去跑匹配串,要注意的是這裡不在是僅有小寫字母,題目中說到:以上字串中的字元都是ASCII碼可見字元(不包括回車)。由於我們需要記錄每個匹配串匹配結果資訊,我們可以開一個儲存空間儲存這些資訊。

  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<string.h>
  4 #include<queue>
  5 using namespace std;
  6 
  7 #define maxn 100005
  8 
  9 char a[505][205];
 10 int trie[maxn][130];
 11 int fail[maxn];
 12 int idword[maxn];
 13 int cnt=0;
 14 
 15 void insertWords(int id)
 16 {
 17     int len=strlen(a[id]);
 18     int now=0;
 19     for(int i=0;i<len;i++)
 20     {
 21         int next=a[id][i];
 22         if(!trie[now][next])
 23             trie[now][next]=++cnt;
 24         now=trie[now][next];
 25     }
 26     idword[now]=id;
 27 }
 28 
 29 void getFail()
 30 {
 31     queue<int> q;
 32     while(!q.empty()) q.pop();
 33     for(int i=0;i<130;i++)
 34     {
 35         if(trie[0][i]){
 36             fail[trie[0][i]]=0;
 37             q.push(trie[0][i]);
 38         }
 39     }
 40     int now=0;
 41     while(!q.empty()){
 42         int now=q.front();
 43         q.pop();
 44         for(int i=0;i<130;i++){
 45             if(trie[now][i]){
 46                 fail[trie[now][i]]=trie[fail[now]][i];
 47                 q.push(trie[now][i]);
 48             }
 49             else trie[now][i]=trie[fail[now]][i];
 50         }
 51     }
 52 }
 53 int an[505];
 54 int anss=0;
 55 void getans(char s[])
 56 {
 57     int len=strlen(s);
 58     int now=0;
 59     for(int i=0;i<len;i++){
 60         now=trie[now][s[i]];
 61         for(int j=now;j&&idword[j]!=0;j=fail[j]){
 62             if(!an[idword[j]])
 63             {
 64                 an[idword[j]]=1;
 65             anss++;
 66             }
 67         }
 68     }
 69 }
 70 
 71 int main()
 72 {
 73     int n,m;
 74     scanf("%d",&n);
 75     for(int i=1;i<=n;i++)
 76     {
 77         scanf("%s",a[i]);
 78         insertWords(i);
 79     }
 80     getFail();
 81     fail[0]=0;
 82     scanf("%d",&m);
 83     char s[10005];
 84     int ans=0;
 85     for(int i=1;i<=m;i++)
 86     {
 87         anss=0;
 88         memset(an,0,sizeof(an));
 89         scanf("%s",s);
 90         getans(s);
 91         if(anss!=0){
 92             //printf("anss=%d\n",anss);
 93             ans++;
 94             printf("web %d: ",i);
 95             for(int j=1;j<=n;j++)
 96             {
 97                 if(an[j]){
 98                     anss--;
 99                     if(anss)
100                         printf("%d ",j);
101                     else {
102                         printf("%d\n",j);break;
103                     }
104                 }
105             }
106         }
107     }
108     printf("total: %d\n",ans);
109     return 0;
110 }
hdu2896