ZOJ 3430 Detect the Virus(AC自动机 + 模拟)题解
题意:问你主串有几种模式串。但是所有串都是加密的,先解码。解码过程为:先把串按照他给的映射表变成6位数二进制数,然后首尾衔接变成二进制长串,再8位8位取变成新的数,不够的补0。因为最多可能到255,所以不能用char存,要用int。
思路:模拟乱搞一下,加个板子完事。
代码:
#include<cmath> #include<set> #include<map> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include <iostream> #include<algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn = 550 * 64 + 10; const int M = maxn * 30; const ull seed = 131; const int INF = 0x3f3f3f3f; const int MOD = 1000000007; char s[maxn]; int bit[maxn * 8], now[maxn * 8]; map<int, int> change; void init(){ change.clear(); for(int i = 0; i <= 25; i++) change['A' + i] = i; for(int i = 26; i <= 51; i++) change['a' + i - 26] = i; for(int i = 52; i <= 61; i++) change['0' + i - 52] = i; change['+'] = 62; change['/'] = 63; } int sp(){ int len = strlen(s); int num = 0; for(int i = 0; i < len; i++){ if(s[i] == '='){ num -= 2; continue; } int k = change[s[i]]; for(int j = 5; j >= 0; j--){ bit[num++] = ((k & (1 << j)) == 0? 0 : 1); } } int cnt = 0; for(int i = 0; i < num; i += 8){ now[cnt] = 0; for(int j = i; j <= i + 7; j++){ now[cnt] = now[cnt] * 2 + bit[j]; } cnt++; } return cnt; } struct Aho{ struct state{ int next[260]; int fail, cnt; }node[maxn]; int size; queue<int> q; void init(){ size = 0; newtrie(); while(!q.empty()) q.pop(); } int newtrie(){ memset(node[size].next, 0, sizeof(node[size].next)); node[size].cnt = node[size].fail = 0; return size++; } void insert(int s[], int len, int id){ int now = 0; for(int i = 0; i < len; i++){ int c = s[i]; if(node[now].next[c] == 0){ node[now].next[c] = newtrie(); } now = node[now].next[c]; } node[now].cnt = id; } void build(){ node[0].fail = -1; q.push(0); while(!q.empty()){ int u = q.front(); q.pop(); for(int i = 0; i < 260; i++){ if(node[u].next[i]){ if(u == 0) node[node[u].next[i]].fail = 0; else{ int v = node[u].fail; while(v != -1){ if(node[v].next[i]){ node[node[u].next[i]].fail = node[v].next[i]; break; } v = node[v].fail; } if(v == -1) node[node[u].next[i]].fail = 0; } q.push(node[u].next[i]); } } } } set<int> res; void get(int u){ //匹配规则 while(u){ if(node[u].cnt) res.insert(node[u].cnt); u = node[u].fail; } } int match(int s[], int len){ res.clear(); int ret = 0, now = 0; for(int i = 0; i < len; i++){ int c = s[i]; if(node[now].next[c]){ now = node[now].next[c]; } else{ int p = node[now].fail; while(p != -1 && node[p].next[c] == 0){ p = node[p].fail; } if(p == -1) now = 0; else now = node[p].next[c]; } get(now); } return res.size(); } }ac; int main(){ init(); int n; while(~scanf("%d", &n)){ ac.init(); for(int i = 1; i <= n; i++){ scanf("%s", s); int len = sp(); ac.insert(now, len, i); } ac.build(); int m; scanf("%d", &m); while(m--){ scanf("%s", s); int len = sp(); printf("%d\n", ac.match(now, len)); } printf("\n"); } return 0; }