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 }