Detect the Virus - ZOJ 3430(恶心的自动机)

题目大意:给你一些病毒的特征码,然后再给一些文本,判断每个文本有多少种病毒,不过给的字符串都是加密处理过的,给的每个字符串都有对应一个64以内的一个数(题目里面那个表就是),然后可以把这个64以内的这个数化成6位的二进制数,然后把这些二进制数每8位再化成一个字符,这就是原来的字符,比如 QA== ->编号0 1->二进制010000 000000->每8位变成一个字符 01000000 0000(后面这4个0就是那两个==,可以舍去)-> 64('@')。
 
分析:因为是化成8位的二进制,2^8 = 256,不过因为有‘\0’这样的字符,所以无法使用char来搞,开一个int数组是个不错的选择,当然也得注意内存开销,申请内存的方式会MLE,实验得出结果开6W最好.....真是让人感觉很恶心,错了19次!!
 
代码如下:
===============================================================================================================================

 

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;

const int MAXN = 10007;
const int MAXM = 256;///2^8
const int oo = 1e9+37;

const char cb64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int virus[MAXN], MumStr[MAXN];
char s[MAXN];
int password[MAXN*8];

struct node
{
    int Fail, next[MAXM];
    int leaf, num;

    void InIt()
    {
        Fail = leaf = num = 0;
        memset(next, 0, sizeof(next));
    }

}trie[60000];
int top;

int TurnStr(char s[], int p[])
{
    int i, j, k=0;

    for(i=0; s[i] && s[i] != '='; i++)
    {
        s[i] = strchr(cb64, s[i]) - cb64;

        for(j=5; j>=0; j--)
        {
            password[k+j] = s[i] % 2;
            s[i] /= 2;
        }

        k += 6;
    }

    int len = 0;

    for(i=j=0; i<k; i++)
    {
        j = j*2 + password[i];

        if((i+1) % 8 == 0)
        {
            p[len++] = j;
            j = 0;
        }
    }

    return len;
}
void Insert(int root, int N)
{
    int p = root;

    for(int i=0; i<N; i++)
    {
        int k = virus[i];

        if(trie[p].next[k] == 0)
        {
            trie[p].next[k] = ++top;
            trie[top].InIt();
        }
        p = trie[p].next[k];
    }

    trie[p].leaf += 1;
}
void GetFail(int root)
{
    int p = root, temp;
    queue<int> Q;

    trie[root].Fail = -1;

    for(int i=0; i<MAXM; i++)if(trie[p].next[i])
    {
        int k = trie[p].next[i];

        trie[k].Fail = root;
        Q.push(k);
    }

    while(Q.size())
    {
        p = Q.front();
        Q.pop();

        for(int i=0; i<MAXM; i++)if(trie[p].next[i])
        {
            int k = trie[p].next[i];
            temp = trie[p].Fail;

            while(temp != -1)
            {
                if(trie[temp].next[i])
                {
                    trie[k].Fail = trie[temp].next[i];
                    break;
                }

                temp = trie[temp].Fail;
            }

            if(temp == -1)
                trie[k].Fail = root;

            Q.push(k);
        }
    }
}
int Query(int root, int N, int num)
{
    int sum = 0;
    int p = root, temp;

    for(int i=0; i<N; i++)
    {
        int k = MumStr[i];

        while(!trie[p].next[k] && p!=root)
            p = trie[p].Fail;

        if(!trie[p].next[k])continue;

        temp = p = trie[p].next[k];

        while(temp != root && trie[temp].num != num)
        {
            if(trie[temp].leaf)
                sum += 1;
            trie[temp].num = num;
            temp = trie[temp].Fail;
        }
    }

    return sum;
}

int main()
{
    int N, M;

    while(scanf("%d", &N) != EOF)
    {
        int root = 0;

        trie[0].InIt();
        top = 0;

        for(int i=1; i<=N; i++)
        {
            scanf("%s", s);
            int len = TurnStr(s, virus);

            Insert(root, len);
        }

        GetFail(root);
        scanf("%d", &M);

        for(int i=1; i<=M; i++)
        {
            scanf("%s", s);
            int len = TurnStr(s, MumStr);

            printf("%d\n", Query(root, len, i));
        }
        printf("\n");
    }

    return 0;
}

 

 

 

posted @ 2015-08-23 10:11  无忧望月  阅读(189)  评论(0编辑  收藏  举报
levels of contents