• ZOJ3430 Detect the Virus [AC自动机]


      这道题好坑啊,整整调了我一下午!!

      题意很简单,就是一个裸的自动机加上解码。编码是使用8位ASCII码连接字符,然后6位一取,结尾不足6位用0补上,每6位二进制数都会对应一个字符,形成了新的字符串。解码后最好用int存每一位的内容,写起来比较方便,因为可能会有'\0'这样的字符出现。。

      一开始写了个位运算版本的解码,但是一直WA。于是写了个很暴力的模拟二进制解码,竟然A了,看来自动机部分没什么问题。然后又回过头来调我的位运算版解码,怎么算都没有错啊,但是就是一直WAWAWA。。。。最后绝望之中改了下数组大小,把字符串数组从2500改成了5000。。。然后,然后就神奇的A了。。跑了130ms。。这尼玛是什么状况,难道2048bytes不是说2048位么。。就算不是,为啥越界不给我RE。。就算不给RE,为啥暴力的解码就过了。。。

      

    #include <stdio.h>
    #include <string.h>
    #include <queue>
    #define MAXN 40000
    int n,m;
    char ss[5000];
    int sn[2500],slen,ctk[256];
    //解码
    void codestr(char* s){
        slen=0;
        for(int i=0,len=0,x=0;s[i]&&s[i]!='=';i++){
            len+=6, x=x<<6|ctk[s[i]];
            if(len>=8){
                sn[slen++]=((x>>(len-8))&0xff);
                len-=8;
            }
        }
    }
    //自动机
    int next[MAXN][256],fail[MAXN],cnt[MAXN],cal[MAXN],pos;
    int newnode(){
        for(int i=0;i<256;i++)next[pos][i]=0;
        fail[pos]=cnt[pos]=cal[pos]=0;
        return pos++;
    }
    void insert(int *s,int len,int id){
        int p=0;
        for(int i=0;i<len;i++){
            int &x=next[p][s[i]];
            p=x?x:x=newnode();
        }
        cnt[p]=id;
    }
    void makenext(){
        std::queue<int> q;
        q.push(0);
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=0;i<256;i++){
                int v=next[u][i];
                if(v==0)next[u][i]=next[fail[u]][i];
                else q.push(v);
                if(u!=0)fail[v]=next[fail[u]][i];
            }
        }
    }
    int findvirus(int *s,int len,int id){
        int ans=0;
        for(int i=0,p=0;i<len;i++){
            p=next[p][s[i]];
            for(int f=p;f&&cal[f]!=id;f=fail[f]){
                cal[f]=id;
                if(cnt[f]>0)ans++;
            }
        }
        return ans;
    }
    int main(){
        for(int c=0;c<256;c++){
            if(c>='A'&&c<='Z')ctk[c]=c-'A';
            else if(c>='a'&&c<='z')ctk[c]=c-'a'+26;
            else if(c>='0'&&c<='9')ctk[c]=c-'0'+52;
            else if(c=='+')ctk[c]=62;
            else if(c=='/')ctk[c]=63;
        }
        //freopen("test.in","r",stdin);
        while(scanf("%d",&n)!=EOF){
            pos=0;newnode();
            for(int i=1;i<=n;i++){
                scanf("%s",ss);
                codestr(ss);
                insert(sn,slen,i);
            }
            makenext();
            scanf("%d",&m);
            for(int i=1;i<=m;i++){
                scanf("%s",ss);
                codestr(ss);
                int x=findvirus(sn,slen,i);
                printf("%d\n",x);
            }
            printf("\n");
        }
        return 0;
    }
  • 相关阅读:
    cocos2dx进阶学习之CCDirector
    cocos2d-x游戏开发系列教程-超级玛丽03-main函数
    磁盘管理
    磁盘同步操作
    导入、导出一个卷组
    创建VG
    IBM磁盘阵列及文件系统的管理
    AIX查看HBA卡的WWN号
    AIX设备四种状态
    AIX 适配器
  • 原文地址:https://www.cnblogs.com/swm8023/p/2624131.html
Copyright © 2020-2023  润新知