1. 程式人生 > >POJ3630/HDU-1671 Phone List,字典樹靜態建樹!

POJ3630/HDU-1671 Phone List,字典樹靜態建樹!

    POJ動態建樹TLE了~~~

    題意:撥打某個電話時可能會因為和其他電話號碼的前幾位重複而導致錯誤,現在給出一張電話單,求是否有某個電話是其他電話的字首。是則輸出NO,否則輸出YES。

    思路:字典樹模板題了,但有一個動態建樹每次都要清空記憶體這個很重要,很容易導致MLE了。這個題插入和查詢可以放在一起,這便是字典樹的強大之處。

struct Tree
{
    bool f;
    Tree *next[N];
};
int insert(Tree *root,char *s)
{
    int sign=0;
    Tree *p=root;
    while(*s!='\0')
    {
        if(p->next[*s-'0']==NULL)
        {
            Tree *temp=new Tree;
            for(int i=0; i<N; i++) temp->next[i]=NULL;
            temp->f=false;
            p->next[*s-'0']=temp;
        }
        if(p->f) sign=1;
        p=p->next[*s-'0'];
        s++;
    }
    p->f=true;//構成了一個單詞或者電話
    for(int i=0; i<N&&!sign; i++) if(p->next[i]!=NULL)  sign=1;//這條路徑還可以走下去,說明前面的都重複了
    return sign;
}
void del(Tree *root)
{
    for(int i=0; i<N; i++)
        if(root->next[i]!=NULL)
            del(root->next[i]);
    delete(root);
}
int main()
{
    int t,n;
    char s[15];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        int f=0;
        Tree *root=new Tree;
        for(int i=0;i<N;i++) root->next[i]=NULL;//初始化子節點;
        root->f=false;
        for(int i=0; i<n; i++)
        {
            scanf("%s",s);
            if(!f) f=insert(root,s);
        }
        if(f) printf("NO\n");
        else printf("YES\n");
        del(root);//每次都要清空記憶體;
    }
    return 0;
}


/*****************************************
*****************   LYQ    ***************
*****************   YES    ***************
*UserID: secrecy                         *
*RunOJ:                                  *
*RunID:                                  *
*Submit time:                            *
*Language: G++                           *
*Result: Accepted                        *
*time:                                   *
*Memory:                                 *
*Length:                                 *
*School: NYIST                           *
*Blog: http://blog.csdn.net/nyist_tc_lyq *
*QQ:                                     *
*Tel:                                    *
*****************************************/

    一模一樣的題,杭電上用動態建樹過了,這裡就超時了,建樹反覆分配和釋放記憶體的問題,所以可以用靜態樹進行優化一下,開一個Tree的陣列,注意開大一點,太大或太小都會MLE。陣列開60010差不多可以了。

int cnt;
struct Tree
{
    bool f;
    Tree *next[N];
};
Tree memory[60005];
int insert(Tree *root,char *s)
{
    int sign=0;
    Tree *p=root;
    while(*s!='\0')
    {
        if(p->next[*s-'0']==NULL)
        p->next[*s-'0']=&memory[cnt++];
        if(p->f) sign=1;
        p=p->next[*s-'0'];
        s++;
    }
    p->f=true;
    for(int i=0; i<N&&!sign; i++) if(p->next[i]!=NULL)  sign=1;
    return sign;
}
int main()
{
    int t,n;
    char s[15];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        int f=0;
        cnt=0;
        memset(memory,0,sizeof(memory));//清空
        Tree *root=&memory[cnt++];//已經開闢好了記憶體,不用每次都分配了。
        for(int i=0; i<n; i++)
        {
            scanf("%s",s);
            if(!f) f=insert(root,s);
        }
        if(f) printf("NO\n");
        else printf("YES\n");
    }
    return 0;
}
//能理解但是不會用,關於記憶體分配和釋放這一塊比較薄弱,貌似平時用的也不多~~

/*****************************************
*****************   LYQ    ***************
*****************   YES    ***************
*UserID: secrecy                         *
*RunOJ:                                  *
*RunID:                                  *
*Submit time:                            *
*Language: G++                           *
*Result: Accepted                        *
*time:                                   *
*Memory:                                 *
*Length:                                 *
*School: NYIST                           *
*Blog: http://blog.csdn.net/nyist_tc_lyq *
*QQ:                                     *
*Tel:                                    *
*****************************************/