HDU 3695 Computer Virus on Planet Pandora

来源:互联网 发布:淘宝卖家号出售平台 编辑:程序博客网 时间:2024/05/22 04:29

【题意】

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

【解题方法】

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

这题我咋死活过不了啊。最后连输入外挂都上了,还是TLE。可能是模板问题?我找了一份AC代码,先放上来,下来研究研究。可能是我的AC自动机太慢?

【别人的AC 代码】原创地址


#include <stdio.h>#include <string.h>#include <queue>using namespace std;#define N 251#define NODE 500010#define LEN 5100010int 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;}

【我的死活过不来了代码,下来研究研究】

#include <queue>#include <cstdio>#include <ctype.h>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 5100100;const int maxm = 500010;const int maxs = 26;char s[1010];int nn;char s1[maxn],s2[maxn],s3[maxn];int len2;void read(){    char c;    int p=0,t=0;    while(c=getchar(),c!='\n')    {        if(t==0&&(c>='A'&&c<='Z'))        {            s1[p++]=c;        }        else if(t!=0&&(c>='A'&&c<='Z'))        {            while(t--)s1[p++]=c;        }        else if(c=='['||c==']')        {            t=0;        }        else if(c>='0'&&c<='9')        {            t=t*10+c-48;        }    }    s1[p]='\0';}void change(){    int len1=strlen(s1),num,i,j;    len2=0;    for(i=0;i<len1;i++){        if(s1[i]>='A'&&s1[i]<='Z'){            s2[len2++]=s1[i];            continue;        }        if(s1[i]=='['){            i++;            num=0;            for(;s1[i]>='0'&&s1[i]<='9';i++){                num=num*10+s1[i]-'0';            }            int ll=len2;            for(j=ll;j<ll+num;j++){                s2[j]=s1[i];                len2++;            }            i+=1;        }    }    s2[len2]='\0';    for(i=0;i<len2;i++){        s3[i]=s2[len2-i-1];    }    s3[len2]='\0';}struct Acautomata{    int root,sz;    int nxt[maxm][maxs],fail[maxm],cnt[maxm];    int newnode()    {        cnt[sz]=0;        memset(nxt[sz],-1,sizeof(nxt[0]));        return sz++;    }    void init()    {        sz=0;        root=newnode();    }    void Insert(char *s)    {        int u=root,n=strlen(s);        for(int i=0; i<n; i++)        {            int &v=nxt[u][s[i]-'A'];            if(v==-1) v=newnode();            u=v;        }        ++cnt[u];    }    void build()    {        queue<int>q;        fail[root]=root;        for(int i=0; i<maxs; i++){            int &v=nxt[root][i];            if(~v){                fail[v]=root;                q.push(v);            }else{                v=root;            }        }        while(q.size())        {            int u=q.front();q.pop();            for(int i=0; i<maxs; i++)            {                int &v=nxt[u][i];                if(~v){                    fail[v]=nxt[fail[u]][i];                    q.push(v);                }else{                    v=nxt[fail[u]][i];                }            }        }    }    int queryans(char *s)    {        int u=root,n=strlen(s);        int ans=0;        for(int i=0; i<n; i++)        {            u=nxt[u][s[i]-'A'];            for(int v=u; v!=root; v=fail[v]){                ans+=cnt[v];                cnt[v]=0;            }        }        return ans;    }}ac1;int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d",&nn);        ac1.init();        for(int i=1; i<=nn; i++)        {            scanf("%s",s);            ac1.Insert(s);        }        getchar();        ac1.build();        read();        //cout<<s1<<endl;        change();        int ans = 0;        ans += ac1.queryans(s2);        ans += ac1.queryans(s3);        printf("%d\n",ans);    }    return 0;}


0 0