ZOJ 3430 Detect the Virus 【AC自动机+解码】

解码的那些事儿,不多说。

注意解码后的结果各种情况都有,用整数数组存储,char数组会超char类型的范围(这个事最蛋疼的啊)建立自动机的时候不能用0来判断结束。


 

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <string>
#include <iostream>
using namespace std;
vector<int> ans;

struct AC_Automata {
    #define N 60010
    #define M 256
    int ch[N][M], sz;
    int val[N], last[N], f[N], cc[N];

    void clear() {
        sz = 1;
        memset(ch[0], 0, sizeof(ch[0]));
    }

    void insert(int s[], int l, int v) {
        int u = 0;
        for (int i=0; i<l; i++) {
            int c = s[i];
            if (!ch[u][c]) {
                memset(ch[sz], 0, sizeof(ch[sz]));
                val[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        val[u] = v;
    }
    void build() {
        queue<int> q;
        f[0] = 0;
        for (int c=0; c<M; c++) {
            int u = ch[0][c];
            if (u) { f[u] = last[u] = 0; q.push(u); }
        }
        while (!q.empty()) {
            int r = q.front(); q.pop();
            for (int c=0; c<M; c++) {
                int u = ch[r][c];
                if (!u) { ch[r][c] = ch[f[r]][c]; continue; }
                q.push(u);
                f[u] = ch[f[r]][c];
                last[u] = val[f[u]] ? f[u] : last[f[u]];
            }
        }
    }
    void find(int s[], int l) {
        int j = 0;
        for (int i=0; i<l; i++) {
            int c = s[i];
            j = ch[j][c];

            if (val[j]) print(j);
            else if (last[j]) print(last[j]);
        }
    }
    void print(int j) {
        if (j) {
            ans.push_back(val[j]);
            print(last[j]);
        }
    }
} ac;
int get(char c) {
    if (c >= 'A' && c <= 'Z') return c-'A';
    if (c >= 'a' && c <= 'z') return c-'a'+26;
    if (c >= '0' && c <= '9') return c-'0'+ 52;
    if (c == '+') return 62;
    return 63;
}

int ss[30002];
int bit[30003*10];

int decode(char str[]) {
    int top = 0;
    int a[10];

    for(int i=0; str[i]; i++) {
        if(str[i]!='='){
            int x = get(str[i]);
            for(int j=5;j>=0;j--){
                a[j] = x & 1;
                x >>= 1;
            }
            for (int j=0; j<6; j++) bit[top++] = a[j];
        }else
            top -= 2;
    }

    int x = 0;
    int tot = 0;
    for(int i=0;i<top;){
        x = 0;
        for(int j=0;j<8;j++)
            x = x<<1 | bit[i++];
        ss[tot++] = x;
    }
    return tot;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif


    int n, m;
    char s[30023];

    while (scanf(" %d", &n) == 1) {
        ac.clear();
        for (int i=1; i<=n; i++) {
            scanf(" %s", s);
            int l = decode(s);
            ac.insert(ss, l, i);
        }
        ac.build();

        scanf(" %d", &m);
        while (m--) {
            ans.clear();
            scanf(" %s", s);
            int l = decode(s);
            ac.find(ss, l);

            sort(ans.begin(), ans.end());
            int cnt = unique(ans.begin(), ans.end()) - ans.begin();
            printf("%d\n", cnt);
        }

        puts("");
    }

    return 0;
}


 

 

posted @ 2013-08-08 21:55  坚固66  阅读(195)  评论(0编辑  收藏  举报