POJ3630 Phone List+字典数三种申请内存的方法--动态、静态、半动态

POJ3630Phone List+字典数三种动态和静态申请内存的方法  

Description:

Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let's say the phone catalogue listed these numbers:

  • Emergency 911
  • Alice 97 625 999
  • Bob 91 12 54 26

In this case, it's not possible to call Bob, because the central would direct your call to the emergency line as soon as you had dialled the first three digits of Bob's phone number. So this list would not be consistent.

Input

The first line of input gives a single integer, 1 ≤ t ≤ 40, the number of test cases. Each test case starts with n, the number of phone numbers, on a separate line, 1 ≤ n ≤ 10000. Then follows n lines with one unique phone number on each line. A phone number is a sequence of at most ten digits.

Output

For each test case, output "YES" if the list is consistent, or "NO" otherwise.

Sample Input

2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
Sample Output

NO
YES

题意很简单:就是给你一系列的字符串,容易过其中有一个字符串是其中一个字符串的前缀,就输出NO,否则输出YES。

解题思路也不难,只要在建树把字符串一个个放进去,然后边放边判断。这里要注意的是判断的时候分类讨论:1、现在判断的字符串之前放进去的字符串的前缀 2、之前放进去的字符串是现在判断的字符串的前缀。


这里然后介绍三种申请内存的方法

1、动态申请内存,这个是三种里面速度最慢的,因为要逐个的去申请结构体的内存。(针对这道题目,在杭电的HDU1671能过,但在POJ上却过不了,这个让我当初在POJ上TLE了无数次)

<pre name="code" class="html">#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 10
char s[30];
bool flag;
typedef struct tree{
    tree *next[MAX];
    bool v;
};
tree *root;
void creattree(char *str)
{
    tree *p=root,*q;
    int n=strlen(str);
    for(int i=0;i<n;i++)
    {
        int id=str[i]-'0';
        if(p->next[id]==NULL)
        {
            q=(tree *)malloc(sizeof(tree));    ///动态申请内存
            q->v=0;
            for(int j=0;j<MAX;j++)
            {
                q->next[j]=NULL;
            }
            p->next[id]=q;
            p=p->next[id];
        }
        else
        {
            p=p->next[id];
            if(p->v||i==n-1) {flag=1;break;}
        }
    }
    p->v=1;
}
int dele(tree *t)
{
    if(t==NULL) return 0;
    else
    {
        for(int i=0;i<MAX;i++)
        {
            if(t->next[i]!=NULL)
                dele(t->next[i]);
        }
    }
    free(t);
    return 0;
}
int main()
{
    int to;
    scanf("%d",&to);
        while(to--)
        {
            root=(tree *)malloc(sizeof(tree));      //动态申请内存
            root->v=0;
            for(int i=0;i<MAX;i++) root->next[i]=NULL;
            int n;
            flag=0;
            scanf("%d",&n);
            for(int i=0;i<n;i++)
            {
                scanf("%s",s);
                if(!flag) creattree(s);
            }
            if(flag) printf("NO\n");
                else printf("YES\n");
                dele(root);
        }
}


 
 
 

 

第二种是静态申请内存,也就是开个结构体数组,这种方法耗时最短,但是有个坏处就是如果题目没有告诉你要申请的结构体的数目,你开太少的话会RE,开太多容易爆掉,不过这种写法还是最普及的写法。(这种写法在POJ3630和HDU1671都能过)

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 10
const int N = 1000000;
char s[30];
bool flag;
typedef struct tree{
    tree *next[MAX];
    bool v;
};
tree dot[N],*bat;     ///申请结构体数组
tree *newNode()
{
    tree *p = bat++;
    for(int i=0;i<MAX;i++)
    {
        p->next[i]=NULL;
        p->v=0;
    }
    return p;
}
tree *root;
void creattree(char *str)
{
    tree *p=root,*q;
    int n=strlen(str);
    for(int i=0;i<n;i++)
    {
        int id=str[i]-'0';
        if(p->next[id]==NULL)
        {
            q=newNode();
            p->next[id]=q;
            p=p->next[id];
        }
        else
        {
            p=p->next[id];
            if(p->v||i==n-1) {flag=1;break;}
        }
    }
    p->v=1;
}
void memin()
{
    bat=dot;
    root=newNode();
}
int main()
{
    int to;
    scanf("%d",&to);
        while(to--)
        {
            memin();
            int n;
            flag=0;
            scanf("%d",&n);
            for(int i=0;i<n;i++)
            {
                scanf("%s",s);
                if(!flag) creattree(s);
            }
            if(flag) printf("NO\n");
                else printf("YES\n");
        }
}
第三种方法为半动态申请,这种方法在处理上应该是最优的,既克服了动态申请内存时间太慢的缺点,又避免了静态申请内存数组大小不好控制的缺点。这种方法的原理就是一次性申请一个范围适中的结构体数组,比如这题可以开个10000,然后不够的时候再开,但是要把这些结构体给连上,最后拿来重新利用。实现方法如下:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 10
const int N = 10000;
char s[30];
bool flag;
typedef struct tree{
    tree *next[MAX];
    bool v;
};
tree *List;
tree *newNode()
{
    if(List==NULL)				//如果10000个结构体用完可以继续申请
    {
        tree *p=new tree[10000];
        for(int i=0;i<10000;i++)
        {
            p[i].next[0]=List;		///这里两行把结构体连接起来
            List=p+i;			///
        }
    }
    tree *p=List;
    List=List->next[0];
    for(int i=0;i<MAX;i++)
    {
        p->next[i]=NULL;
        p->v=0;
    }
    return p;
}
tree *root;
void creattree(char *str)
{
    tree *p=root,*q;
    int n=strlen(str);
    for(int i=0;i<n;i++)
    {
        int id=str[i]-'0';
        if(p->next[id]==NULL)
        {
            q=newNode();
            p->next[id]=q;
            p=p->next[id];
        }
        else
        {
            p=p->next[id];
            if(p->v||i==n-1) {flag=1;break;}
        }
    }
    p->v=1;
}
void reuse(tree *o)			///退回去重新利用
{
    if(o==NULL) return;
    for(int i=0;i<MAX;i++)
    {
        reuse(o->next[i]);
    }
    o->next[0] = List;
    List = o;
}
int main()
{
    int to;
    scanf("%d",&to);
        while(to--)
        {
            root=newNode();
            int n;
            flag=0;
            scanf("%d",&n);
            for(int i=0;i<n;i++)
            {
                scanf("%s",s);
                if(!flag) creattree(s);
            }
            if(flag) printf("NO\n");
                else printf("YES\n");
                reuse(root);
        }
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值