ZOJ 3430 Detect the Virus(AC自动机)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3430

题意:给你n个编码后的模式串,和m个编码后的主串,求原来主串中含有模式串的个数

思路:首先要将模式串解码成未编码前来建立ac自动机,然后解码主串扫描统计即可。

code:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 #include <set>
  5 using namespace std;
  6 const int KIND = 256;
  7 const int MAXN = 32800;
  8 
  9 struct Trie
 10 {
 11     int next[MAXN][KIND], fail[MAXN], id[MAXN];
 12     int root, L, num;
 13     int create()
 14     {
 15         for (int i = 0; i < KIND; ++i)
 16             next[L][i] = -1;
 17         return L++;
 18     }
 19     void init()
 20     {
 21         L = 0;
 22         num = 0;
 23         memset(id, 0, sizeof(id));
 24         root = create();
 25     }
 26     void insert(unsigned char str[], int len)
 27     {
 28         int now = root;
 29         for (int i = 0; i < len; ++i)
 30         {
 31             if (-1 == next[now][str[i]])
 32                 next[now][str[i]] = create();
 33             now = next[now][str[i]];
 34         }
 35         id[now] = ++num;
 36     }
 37     void build()
 38     {
 39         queue<int>Q;
 40         fail[root] = root;
 41         for (int i = 0; i < KIND; ++i)
 42         {
 43             if (-1 == next[root][i])
 44                 next[root][i] = root;
 45             else
 46             {
 47                 fail[next[root][i]] = root;
 48                 Q.push(next[root][i]);
 49             }
 50         }
 51         while (!Q.empty())
 52         {
 53             int now = Q.front();
 54             Q.pop();
 55             for (int i = 0; i < KIND; ++i)
 56             {
 57                 if (-1 == next[now][i])
 58                     next[now][i] = next[fail[now]][i];
 59                 else
 60                 {
 61                     fail[next[now][i]] = next[fail[now]][i];
 62                     Q.push(next[now][i]);
 63                 }
 64             }
 65         }
 66     }
 67     int query(unsigned char str[], int len)
 68     {
 69         set<int>S;
 70         int now = root;
 71         for (int i = 0; i < len; ++i)
 72         {
 73             now = next[now][str[i]];
 74             int temp = now;
 75             while (temp != root)
 76             {
 77                 if (id[temp]) S.insert(id[temp]);
 78                 temp = fail[temp];
 79             }
 80         }
 81         return (int)S.size();
 82     }
 83 };
 84 
 85 Trie ac;
 86 char buf[4000];
 87 unsigned char temp[4000];
 88 unsigned char str[2500];
 89 
 90 unsigned char Tran(char ch)
 91 {
 92     if (ch >= 'A' && ch <= 'Z') return ch - 'A';
 93     if (ch >= 'a' && ch <= 'z') return ch - 'a' + 26;
 94     if (ch >= '0' && ch <= '9') return ch - '0' + 52;
 95     if (ch == '+') return 62;
 96     return 63;
 97 }
 98 
 99 int Decode(int len)
100 {
101     int k = 0;
102     for (int i = 0; i < len; i += 4)
103     {
104         str[k++] = (temp[i]<<2)|(temp[i + 1]>>4);
105         if (i + 2 < len) str[k++] = (temp[i + 1]<<4)|(temp[i + 2]>>2);
106         if (i + 3 < len) str[k++] = (temp[i + 2]<<6)|(temp[i + 3]);
107     }
108     return k;
109 }
110 
111 int main()
112 {
113     int n, m;
114     while (scanf("%d", &n) != EOF)
115     {
116         ac.init();
117         for (int i = 0; i <n; ++i)
118         {
119             scanf("%s", buf);
120             int len = strlen(buf);
121             while ('=' == buf[len - 1]) --len;
122             for (int j = 0; j < len; ++j) temp[j] = Tran(buf[j]);
123             ac.insert(str, Decode(len));
124         }
125         ac.build();
126         scanf("%d", &m);
127         for (int i = 0; i < m; ++i)
128         {
129             scanf("%s", buf);
130             int len = strlen(buf);
131             while ('=' == buf[len - 1]) --len;
132             for (int j = 0; j < len; ++j) temp[j] = Tran(buf[j]);
133             printf("%d\n", ac.query(str, Decode(len)));
134         }
135         printf("\n");
136     }
137     return 0;
138 }

 

posted @ 2015-06-24 16:44  jasaiq  阅读(268)  评论(0编辑  收藏  举报