HDU 2896 病毒侵袭(AC自动机)

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

题意:给你n个模式串,m个主串,求出每个主串中出现的模式串的标号。

思路:AC自动机水题,trie树中维护标号,m次扫描即可,注意点输出格式。

code:

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

 数组实现:

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

 

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