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 }

 

你可能感兴趣的:(search)