HDU 5880 Family View 好容易MLE的AC自动机 *

来源:互联网 发布:数据 英文 编辑:程序博客网 时间:2024/06/05 20:56

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5880

开结构体,不大好,因为很容易爆空间

额 下面的代码 用的时候就new出来,用完就delete,但还是MLE

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<algorithm>#include<cctype>using namespace std;const int maxn=1000000+5;const int letters=26; struct CNode{    CNode *pChilds[letters];    CNode *pPrev;    bool bBadNode,end; int len;     CNode(){        for(int i=0;i<letters;i++) pChilds[i]=NULL;        bBadNode=end=false; len=0;        pPrev=NULL;    }};char str[maxn];CNode* Q[maxn];int head,tail;void BuildDfa(CNode* root0,CNode* root1){    for(int i=0;i<letters;i++)    root0->pChilds[i]=root1;    root1->pPrev=root0;    root0->pPrev=NULL;    head=tail=0;    Q[head++]=root1;    while(head!=tail)    {        CNode *root=Q[tail++];        for(int i=0;i<letters;i++)        {            CNode *p=root->pChilds[i];            if(p==NULL) continue;            CNode *pPrev=root->pPrev;            while(pPrev){                if(pPrev->pChilds[i]!=NULL){                    p->pPrev=pPrev->pChilds[i];                    if(p->pPrev->bBadNode)                        p->bBadNode=true;                    break;                  }                else pPrev=pPrev->pPrev;               }            Q[head++]=p;        }    }    }bool SearchDfa(CNode* root,char *s){    CNode *p=root;    for(int i=0;s[i];i++){        if(!isalpha(s[i])) continue;        for(;;){            if(p->pChilds[tolower(s[i])-'a']!=NULL){                p=p->pChilds[tolower(s[i])-'a'];                CNode* pPrev=p;                while(pPrev->bBadNode){                if(pPrev->end){                for(int j=0;j<p->len;j++)                        s[i-j]='*';                        break;}pPrev=pPrev->pPrev;                }                 break;            }            else p=p->pPrev;  //到前驱节点         }    }    return false;}void Insert(CNode *root,char *s){    for(int i=0;s[i];i++)    {        if(root->pChilds[s[i]-'a']==NULL)            root->pChilds[s[i]-'a']=new CNode;        root=root->pChilds[s[i]-'a'];    }    root->bBadNode=true;    root->end=true;    root->len=strlen(s);}void Dele(CNode* root){for(int i=0;i<letters;i++)if(root->pChilds[i]!=NULL)Dele(root->pChilds[i]);delete root;}int main(){    int T,n; cin>>T;    while(T--)    {    CNode *root0=new CNode,*root1=new CNode;        cin>>n;        while(n--){            scanf("%s",str);            Insert(root1,str);        }        BuildDfa(root0,root1);        getchar();        gets(str);        SearchDfa(root1,str);        cout<<str<<endl;        Dele(root1);        delete root0;    }    return 0;}




所以还是数组好

试了一下,如果数组没用到,不会计入memory,但是结构体一旦new出来,就要全部算空间

并且什么都不干,单单开个1000000的数组,只要memset就会MLE

以下这句话摘自:博客

Q神说不要用memset一次性清空数组,超内存是我一次性memset数组导致的,将没有用的空间也用上了,于是试了下不一次性memset数组,果断不超了。


#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<algorithm>#include<cctype>using namespace std;const int INF=0x3f3f3f3f;const int maxn=1000000+5;const int letters=26;const int pPrev=26;const int len=27;const int bBadNode=28;const int End=29;int nNode;int tree[maxn][30];char str[maxn];int NewNode()   //用一个就开一个空间 {    for(int i=0;i<30;i++) tree[nNode][i]=-1;    nNode++;    return nNode-1;}void init(){    nNode=2;    for(int i=0;i<30;i++) tree[0][i]=tree[1][i]=-1;}void Insert(int root,char *s){    for(int i=0;s[i];i++){        if(tree[root][s[i]-'a']==-1)            tree[root][s[i]-'a']=NewNode();        root=tree[root][s[i]-'a'];    }    tree[root][len]=strlen(s);    tree[root][bBadNode]=1;    tree[root][End]=1;}void BuildDfa(){    for(int i=0;i<letters;i++)        tree[0][i]=1;    tree[1][pPrev]=0;    tree[0][pPrev]=-1;    queue<int> Q;    Q.push(1);    while(!Q.empty())    {        int root=Q.front(); Q.pop();        for(int i=0;i<letters;i++)        {            int p=tree[root][i];            if(p==-1) continue;            int pp=tree[root][pPrev];            while(pp!=-1)                if(tree[pp][i]!=-1){                    tree[p][pPrev]=tree[pp][i];                    if(tree[tree[p][pPrev]][bBadNode]==1)                        tree[p][bBadNode]=1;                    break;                }                else pp=tree[pp][pPrev];            Q.push(p);        }    }}void SearchDfa(char *s){    int p=1;    for(int i=0;s[i];i++)    {        if(!isalpha(s[i])) {            p=1; continue;        }        for(;;){            if(tree[p][tolower(s[i])-'a']!=-1){                p=tree[p][tolower(s[i])-'a'];                int pp=p;                while(tree[pp][bBadNode]==1){                    if(tree[pp][End]==1){                        for(int j=0;j<tree[pp][len];j++)                            s[i-j]='*';                        break;                    }                    else pp=tree[pp][pPrev];                }                break;                }            else p=tree[p][pPrev];        }    }}int main(){    int T,n; scanf("%d",&T);    while(T--)    {        scanf("%d",&n); nNode=2;        init();        while(n--){            scanf("%s",str);            Insert(1,str);        }        BuildDfa();        getchar();        gets(str);        SearchDfa(str);        cout<<str<<endl;    }    return 0;}



0 0