zoukankan      html  css  js  c++  java
  • HDOJ 3695 Computer Virus on Planet Pandora (AC自动机)

    题意:给n个病毒字符串和一个程序字符串,若程序字符串包含某个病毒字符串或者它的反串,则包含这个病毒,问所给程序字符串包含多少个病毒?

    分析:用病毒串和反串建立AC自动机,然后求包含多少病毒,但同一个病毒可能会被计算2次(如果病毒和它的反串都出现在程序中),对于每个病毒,它在自动机中都有2个结点代表自身结尾和反串结尾,我们对每个病毒都记录这2个结点,在统计的过程中可以把走过的结点打上标记,最后再统计哪些病毒的2个结点都被标记,说明被统计了2次,需要减去一次,这样就没问题了。但是题中说了程序串是压缩的,所以需要先需处理,而且还要考虑嵌套压缩的情况,当时就没考虑到……

    View Code
    #include <stdio.h>
    #include <string.h>
    #include <queue>
    using namespace std;
    #define N 251
    #define NODE 500010
    #define LEN 5100010
    int n,node,x[N],y[N];
    int next[NODE][26],fail[NODE],cnt[NODE];
    bool vis[NODE];
    char S[LEN],tmp[LEN];
    int newnode()
    {
        memset(next[node],0,sizeof(next[0]));
        fail[node]=cnt[node]=0;
        return node++;
    }
    void insert(char *s,int id)
    {
        int i,k,cur;
        for(i=cur=0; s[i]; i++)
        {
            k=s[i]-'A';
            if(!next[cur][k])   next[cur][k]=newnode();
            cur=next[cur][k];
        }
        cnt[cur]++;
        x[id]=cur;
        for(i--,cur=0; i>=0; i--)
        {
            k=s[i]-'A';
            if(!next[cur][k])   next[cur][k]=newnode();
            cur=next[cur][k];
        }
        cnt[cur]++;
        y[id]=cur;
    }
    void makenext()
    {
        queue<int>q;
        int u,v,k;
        q.push(0);
        while(!q.empty())
        {
            u=q.front(),q.pop();
            for(int k=0; k<26; k++)
            {
                v=next[u][k];
                if(v)   q.push(v);
                else    next[u][k]=next[fail[u]][k];
                if(u&&v)    fail[v]=next[fail[u]][k];
            }
        }
    }
    void read()
    {
        char c;
        int p=0,t=0;
        while(c=getchar(),c!='\n')
        {
            if(t==0&&(c>='A'&&c<='Z'))
            {
                S[p++]=c;
            }
            else if(t!=0&&(c>='A'&&c<='Z'))
            {
                while(t--)S[p++]=c;
            }
            else if(c=='['||c==']')
            {
                t=0;
            }
            else if(c>='0'&&c<='9')
            {
                t=t*10+c-48;
            }
        }
        S[p]='\0';
    }
    int main()
    {
        int T;
        char s[1001];
        scanf("%d",&T);
        while(T--)
        {
            node=0,newnode();
            scanf("%d",&n);
            for(int i=0; i<n; i++)
            {
                scanf("%s\n",s);
                insert(s,i);
            }
            makenext();
            read();
    
            int ans=0,i,k,cur;
            memset(vis,0,sizeof(vis));
            for(i=cur=0; S[i]; i++)
            {
                k=S[i]-'A';
                cur=next[cur][k];
                for(int t=cur; t&&cnt[t]!=-1; t=fail[t])
                {
                    ans+=cnt[t];
                    cnt[t]=-1;
                    vis[t]=1;
                }
            }
            for(int i=0; i<n; i++)
            {
                if(vis[x[i]]&&vis[y[i]])    ans--;
            }
            printf("%d\n",ans);
        }
        return 0;
    }
  • 相关阅读:
    01-NoSQL概述
    SSM快速整合
    C语言指针传参与C++引用传参,以及尾插法建立单链表使用到的引用
    IP地址相关
    二叉树的先序遍历、中序遍历、后序遍历-C语言描述
    华为5G认证练习题2
    华为5G认证练习题
    华为ICT学堂获取练习题及答案
    C++ cin对象的一些方法
    webpack学习笔记2:新建工程
  • 原文地址:https://www.cnblogs.com/algorithms/p/2685331.html
Copyright © 2011-2022 走看看