【hdu2222-Keywords Search】AC自动机基础裸题

http://acm.hust.edu.cn/vjudge/problem/16403

题意:给定n个单词,一个字符串,问字符串中出现了多少个单词。(若单词her,he,字符串aher中出现了两个单词)

题解:

每个单词末尾节点sum=1;
find的时候每个点都顺着fail往上跳,加上该节点的sum,然后将这个sum清了;
注意同一个单词出现多次只算一次。

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<queue>
  6 using namespace std;
  7 
  8 const int N=10100,L=1000100;
  9 char s[L];
 10 int num,n;
 11 struct node{
 12     int son[30];
 13     int fail,cnt;
 14 }a[N*60];
 15 queue<int> q;
 16 
 17 void clear(int x)
 18 {
 19     a[x].cnt=0;
 20     a[x].fail=0;
 21     memset(a[x].son,0,sizeof(a[x].son));
 22 }
 23 
 24 void trie(char *c)
 25 {
 26     int l=strlen(c);
 27     int x=0;
 28     for(int i=0;i<l;i++)
 29     {
 30         int t=c[i]-'a'+1;
 31         if(!a[x].son[t])
 32         {
 33             num++;
 34             clear(num);
 35             a[x].son[t]=num;
 36         }
 37         x=a[x].son[t];
 38     }
 39     a[x].cnt++;
 40 }
 41 
 42 void buildAC()
 43 {
 44     while(!q.empty()) q.pop();
 45     for(int i=1;i<=26;i++)
 46         if(a[0].son[i]) q.push(a[0].son[i]);
 47     while(!q.empty())
 48     {
 49         int x=q.front();q.pop();
 50         int fail=a[x].fail;
 51         for(int i=1;i<=26;i++) 
 52         {
 53             int y=a[x].son[i];
 54             if(y)
 55             {
 56                 a[y].fail=a[fail].son[i];
 57                 q.push(y);
 58             }
 59             else a[x].son[i]=a[fail].son[i];
 60         }
 61     }
 62 }
 63 
 64 int find(char *c)
 65 {
 66     int l=strlen(c);
 67     int x=0,ans=0;
 68     for(int i=0;i<l;i++)
 69     {
 70         int t=c[i]-'a'+1;
 71         while(x && !a[x].son[t]) x=a[x].fail;        
 72         x=a[x].son[t];
 73         int p=x;
 74         while(p && a[p].cnt!=-1)
 75         {
 76             ans+=a[p].cnt;
 77             a[p].cnt=-1;
 78             p=a[p].fail;
 79         }
 80     }
 81     return ans;
 82 }
 83 
 84 int main()
 85 {
 86     freopen("a.in","r",stdin);
 87     freopen("a.out","w",stdout);
 88     int T;
 89     scanf("%d",&T);
 90     while(T--)
 91     {
 92         scanf("%d",&n);
 93         num=0;
 94         clear(0);
 95         for(int i=1;i<=n;i++)
 96         {
 97             scanf("%s",s);
 98             trie(s);
 99         }
100         buildAC();
101         scanf("%s",s);
102         printf("%d\n",find(s));
103     }
104     return 0;
105 }

 

posted @ 2016-07-19 21:50  拦路雨偏似雪花  阅读(1529)  评论(1编辑  收藏  举报