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;
}

 

posted @ 2019-07-12 16:38  KirinSB  阅读(260)  评论(0编辑  收藏  举报