HDU 2222 Keywords Search(AC自动机)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2222

题意:给你n个模式串,一个长为m的主串,问有多少个模式串在主串中出现了(模式串可能重复)

思路:AC自动机水题,先根据这n个模式串建立trie树,再构造fail指针,最后扫描主串即可。

code:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 using namespace std;
  5 const int KIND = 26;
  6 
  7 struct node
  8 {
  9     int num;
 10     node* fail;
 11     node* next[KIND];
 12     node()
 13     {
 14         num = 0;
 15         fail = NULL;
 16         for (int i = 0; i < KIND; ++i) next[i] = NULL;
 17     }
 18 };
 19 node* root;
 20 
 21 void Insert(char str[])
 22 {
 23     node* temp = root;
 24     int len = strlen(str);
 25     for (int i = 0; i < len; ++i)
 26     {
 27         int curr = str[i] - 'a';
 28         if (temp->next[curr] == NULL)
 29             temp->next[curr] = new node();
 30         temp = temp->next[curr];
 31     }
 32     ++(temp->num);
 33 }
 34 
 35 void Build()
 36 {
 37     queue<node*> Q;
 38     root->fail = root;
 39     for (int i = 0; i < KIND; ++i)
 40     {
 41         if (root->next[i] == NULL)
 42             root->next[i] = root;
 43         else
 44         {
 45             root->next[i]->fail = root;
 46             Q.push(root->next[i]);
 47         }
 48     }
 49     while (!Q.empty())
 50     {
 51         node* temp = Q.front();
 52         Q.pop();
 53         for (int i = 0; i < KIND; ++i)
 54         {
 55             if (temp->next[i] == NULL)
 56                 temp->next[i] = temp->fail->next[i];
 57             else
 58             {
 59                 temp->next[i]->fail = temp->fail->next[i];
 60                 Q.push(temp->next[i]);
 61             }
 62         }
 63     }
 64 }
 65 
 66 int Query(char str[])
 67 {
 68     int len = strlen(str);
 69     node* temp = root;
 70     int res = 0;
 71     for (int i = 0; i < len; ++i)
 72     {
 73         int curr = str[i] - 'a';
 74         temp = temp->next[curr];
 75         node* x = temp;
 76         while (x != root)
 77         {
 78             res += x->num;
 79             x->num = 0;
 80             x = x->fail;
 81         }
 82     }
 83     return res;
 84 }
 85 
 86 char str[1000010];
 87 int main()
 88 {
 89     int nCase;
 90     scanf("%d", &nCase);
 91     while (nCase--)
 92     {
 93         int n;
 94         scanf("%d", &n);
 95         root = new node();
 96         for (int i = 0; i < n; ++i)
 97         {
 98             scanf("%s", str);
 99             Insert(str);
100         }
101         Build();
102         scanf("%s", str);
103         printf("%d\n", Query(str));
104     }
105     return 0;
106 }

 数组实现:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 using namespace std;
  5 const int KIND = 26;
  6 const int MAXN = 500005;
  7 const int MAXM = 1000005;
  8 
  9 struct Trie
 10 {
 11     int next[MAXN][KIND], fail[MAXN], end[MAXN];
 12     int root, L;
 13 
 14     int create()
 15     {
 16         for (int i = 0; i < KIND; ++i)
 17             next[L][i] = -1;
 18         end[L++] = 0;
 19         return L - 1;
 20     }
 21 
 22     void init()
 23     {
 24         L = 0;
 25         root = create();
 26     }
 27 
 28     void insert(char str[])
 29     {
 30         int now = root;
 31         int len = strlen(str);
 32         for (int i = 0; i < len; ++i)
 33         {
 34             int curr = str[i] - 'a';
 35             if (next[now][curr] == -1)
 36                 next[now][curr] = create();
 37             now = next[now][curr];
 38         }
 39         ++end[now];
 40     }
 41 
 42     void build()
 43     {
 44         queue<int>Q;
 45         fail[root] = root;
 46         for (int i = 0; i < KIND; ++i)
 47         {
 48             if (next[root][i] == -1)
 49                 next[root][i] = root;
 50             else
 51             {
 52                 fail[next[root][i]] = root;
 53                 Q.push(next[root][i]);
 54             }
 55         }
 56         while (!Q.empty())
 57         {
 58             int now = Q.front();
 59             Q.pop();
 60             for (int i = 0; i < KIND; ++i)
 61             {
 62                 if (next[now][i] == -1)
 63                     next[now][i] = next[fail[now]][i];
 64                 else
 65                 {
 66                     fail[next[now][i]] = next[fail[now]][i];
 67                     Q.push(next[now][i]);
 68                 }
 69             }
 70         }
 71     }
 72 
 73     int query(char str[])
 74     {
 75         int now = root;
 76         int len = strlen(str);
 77         int res = 0;
 78         for (int i = 0; i < len; ++i)
 79         {
 80             int curr = str[i] - 'a';
 81             now = next[now][curr];
 82             int temp = now;
 83             while (temp != root)
 84             {
 85                 res += end[temp];
 86                 end[temp] = 0;
 87                 temp = fail[temp];
 88             }
 89         }
 90         return res;
 91     }
 92 };
 93 
 94 Trie ac;
 95 char str[MAXM];
 96 int main()
 97 {
 98     int nCase;
 99     scanf("%d", &nCase);
100     while (nCase--)
101     {
102         int n;
103         scanf("%d", &n);
104         ac.init();
105         for (int i = 0; i < n; ++i)
106         {
107             scanf("%s", str);
108             ac.insert(str);
109         }
110         ac.build();
111         scanf("%s", str);
112         printf("%d\n", ac.query(str));
113     }
114     return 0;
115 }

 

posted @ 2015-06-17 15:43  jasaiq  阅读(182)  评论(0编辑  收藏  举报