ZOJ 3430 detect the virus AC自动机

来源:互联网 发布:手机新三板交易软件 编辑:程序博客网 时间:2024/05/22 05:11
#include<stdio.h>#include<iostream>#include<cstring>#include<queue>using namespace std;int n,m,alen,blen,a[5100],b[5600];struct ACatuomata{    int next[55600][256],fail[55600],idx[55600],last[55600],num,root;    bool vis[55600];    int newnode()    {        memset(next[num],0,sizeof next[num]);        idx[num]=0;        return num++;    }    void init()    {        num=0;        root=newnode();    }    void insert(int *s,int len,int id)    {        int cur=root;        for(int i=0;i<len;++i)        {            int &tmp=next[cur][s[i]];            if(!tmp)tmp=newnode();            cur=tmp;        }        idx[cur]=id;    }    void getfail()    {        queue<int>q;        fail[root]=root;        for(int i=0;i<256;++i)        {            int u=next[root][i];            if(u)            {                last[u]=fail[u]=0;                q.push(u);            }        }        while(!q.empty())        {            int cur=q.front();            q.pop();            for(int i=0;i<256;++i)            {                int u=next[cur][i];                if(u)                {                    fail[u]=next[fail[cur]][i];                    last[u]=idx[fail[u]]?fail[u]:last[fail[u]];                    q.push(u);                }                else next[cur][i]=next[fail[cur]][i];            }        }    }    int query(int *s,int len)    {        memset(vis,0,sizeof vis);        int cur=root,ret=0;        for(int i=0;i<len;++i)        {            cur=next[cur][s[i]];            int tmp=cur;            while(tmp!=root)            {                vis[idx[tmp]]=1;                tmp=last[tmp];            }        }        for(int i=1;i<=n;++i)            ret+=vis[i];        return ret;    }}ac;int DecodeIndex[]={    0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,    0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,    0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x3E,0x40,0x40,0x40,0x3F,    0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x40,0x40,0x40,0x40,0x40,0x40,    0x40,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,    0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x40,0x40,0x40,0x40,0x40,    0x40,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,    0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x40,0x40,0x40,0x40,0x40};void Base64Decode(int* src,int* dest,int srclen){    for(int i=0;i!=srclen/4;i++)    {        *dest=((DecodeIndex[*src]<<2)|((DecodeIndex[*(src+1)]&0x30)>>4))%256;        *(dest+1)=((DecodeIndex[*(src+1)]<<4)|((DecodeIndex[*(src+2)]&0x3C)>>2))%256;        *(dest+2)=(((DecodeIndex[*(src+2)]&0x03)<<6)|(DecodeIndex[*(src+3)]&0x3F))%256;        src+=4;        dest+=3;    }}int main(){    while(~scanf("%d",&n))    {        ac.init();        getchar();        for(int i=1;i<=n;++i)        {            char c;            while(c=getchar())            {                if(c=='\n')break;                a[alen++]=c;                if(c=='=')++blen;            }            Base64Decode(a,b,alen);            blen=alen/4*3-blen;            ac.insert(b,blen,i);            alen=blen=0;        }        ac.getfail();        scanf("%d",&m);        getchar();        while(m--)        {            char c;            while(c=getchar())            {                if(c=='\n')break;                a[alen++]=c;                if(c=='=')++blen;            }            Base64Decode(a,b,alen);            blen=alen/4*3-blen;            printf("%d\n",ac.query(b,blen));            alen=blen=0;        }        puts("");    }}

题意:给出n个匹配串,有m个询问,对于每个询问,会给出一个原串,求原串中出现过几种匹配串。
这个题的匹配串和原串都是加了密的需要自己解密。
比较坑的就是他问的是种类而不是次数。
比如匹配串ab,原串abab,也只会返回1。
所以这个就不能保存cnt然后扫描的时候cnt++
这个题同样不能break。
就多加一个vis数组,也同样保存匹配串的下标,然后把vis[下标]设为1,最后统计有多少vis为1的就是答案,记得每次询问要清空vis。
错了很多次,不过都是没搞懂题意的时候为了弄懂题意而错的。。

0 0
原创粉丝点击