【Ac自动机】Detect the Virus ZOJ - 3430

Link:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3430

#include <bits/stdc++.h>
using namespace std;

/*
题意:给出n个编码后的模板串,然后有M次询问,每次询问输入一个编码后的文本串,
问在编码前,有多少个模板串在文本串中出现过。
*/
const int N = 55000;
const int M = 256;
int num[N],code[N];
int digit[N];
int change(char ch)
{
    if(ch<='Z'&&ch>='A')
        return ch-'A';
    else if(ch<='z'&&ch>='a')
        return 26+ch-'a';
    else if(ch<='9'&&ch>='0')
        return 52+ch-'0';
    else if(ch=='+')
        return 62;
    return 63;
}
int slen;
void translate(char *str)
{
    int l=strlen(str);
    while(str[l-1]=='=')
        l--;
    for(int i=0; i<l; i++)
        num[i]=change(str[i]);
    memset(code,0,sizeof(code));
    memset(digit,0,sizeof(digit));
    slen=0;
    for(int i=0; i<l; i++)
    {
        for(int j=1; j<=6; j++)
        {
            if(num[i]&1)
                digit[(i+1)*6-j]=1;
            else digit[(i+1)*6-j]=0;
            num[i]>>=1;
        }
    }
    for(int i=0; i<l*6/8; i++)
    {
        for(int j=0; j<8; j++)
        {
            code[i]<<=1;
            code[i]+=digit[i*8+j];
        }
    }
    slen=l*6/8;
//    for(int i = 0; i < slen; i++){
//        printf("%d ",code[i]);
//    }
//    puts("");
}

int n;
struct Aho
{
    struct Node
    {
        int nex[M];
        int fail,endd;
    } node[N];
    int Size;

    queue<int> que;
    int newnode()
    {
        memset(node[Size].nex,0,sizeof(node[Size].nex));
        node[Size].fail = node[Size].endd = 0;
        return Size++;
    }

    void init()
    {
        while(!que.empty()) que.pop();
        Size = 0;
        newnode();
    }

    void Insert(int f)
    {
        int len = slen;
        int now = 0;    //当前所在的点
        for(int i = 0; i < len; i++)
        {
            int t = code[i];
            if(node[now].nex[t]==0)
                node[now].nex[t] = newnode();
            now = node[now].nex[t];
        }
        node[now].endd = f;
    }

    void build()
    {
        node[0].fail = 0;
        for(int i = 0; i < M; i++)
        {
            if(node[0].nex[i])
            {
                node[node[0].nex[i]].fail = 0;
                que.push(node[0].nex[i]);
            }
        }
        while(!que.empty())
        {
            int u = que.front();
            que.pop();
            for(int i = 0; i < M; i++)
            {
                if(node[u].nex[i]==0)
                    node[u].nex[i] = node[node[u].fail].nex[i];
                else
                {
                    node[node[u].nex[i]].fail = node[node[u].fail].nex[i];
                    que.push(node[u].nex[i]);
                }
            }
        }
    }

    int vis[N];
    int match()
    {
        memset(vis,0,sizeof(vis));
        int len = slen;
        int res = 0, now = 0;
        for(int i = 0; i < len; i++)
        {
            int t = code[i];
            now = node[now].nex[t];
            int temp = now;
            while(temp)
            {
                if(node[temp].endd)
                    vis[node[temp].endd] = 1;
                temp = node[temp].fail;
            }
        }
        for(int i = 1; i <= n; i++)
        {
            if(vis[i])
                res++;
        }
        return res;
    }
} aho;

char str[N];
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        aho.init();
        for(int i=0; i<n; i++)
        {
            scanf("%s",str);
            translate(str);
            aho.Insert(1+i);
        }
        aho.build();
        int m;
        scanf("%d",&m);
        for(int i=0; i<m; i++)
        {
            scanf("%s",str);
            translate(str);
            printf("%d\n",aho.match());
        }
        puts("");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值