Phone List(POJ-3630 and HDU-1671)(动态数组与静态数组)

题目链接:

http://poj.org/problem?id=3630

http://acm.hdu.edu.cn/showproblem.php?pid=1671

Phone List
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 30683   Accepted: 9051

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

题目大意:

给出一组电话号码,判断其中一个号码是否另一个号码的前缀

题目分析:

这题用字典树来解决。如果用动态的话,malloc,new和delete这些肯定会超时。

所以只能用静态数组。判断条件优化一下,可以把时间将到100ms以内,可惜我不会优化。

记得静态数组开大一点,10000个号码每个号码10位,开100000最保险了。

动态申请内存跟静态数组,由于POJ使用new这一类动态申请内存超时,只能用静态数组提前把需要的内存申请好。

静态申请数组的话空间复杂度较高,动态申请则时间复杂度较高,各有优缺。

下面给出两种方法的代码:

代码1:动态申请

在hdu可以过,poj则超时。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long LL;
int flag;
struct sky
{
    int path;
    int ch;
    int end;
    sky *next[10];
    sky(char ch=' ')
    {
        this -> ch =ch;
        this -> path =this -> end =0;
        for(int i=0; i<10; i++)
            this -> next[i] =NULL;
    }
};
sky *root;
int add(char *s)
{
    sky *t=root;
    while(*s)
    {
        int i=*s-'0';
        if(t->next[i]==NULL)
            t->next[i] = new sky(*s);
        t->next[i]->path++;
        t=t->next[i];
        s++;
        if(t->end>0) //判断路径是否重复
            return 1;
    }
    t->end++;
    if(t->path>1) return 1; //跟上面一样
    return 0;
}
void Delete(sky *x)
{
    for(int i=0; i<10; i++)
        if(x->next[i]!=NULL)
            Delete(x->next[i]);
    delete(x);
}
int main()
{
    int t;
    char num[13];
    scanf("%d",&t);
    while(t--)
    {
        root=new sky; //动态申请内存
        int n;
        scanf("%d",&n);
        flag=0;
        while(n--)
        {
            scanf(" %s",num);
            flag=add(num);
            if(flag) break; //如果已经出现前缀则直接跳出,不处理下面的号码
        }
        if(n>0)
        {
            while(n--)
                scanf(" %s",num);
        }
        if(flag) printf("NO\n");
        else printf("YES\n");
        Delete(root); //不释放内存则会超限
    }
    return 0;
}

代码2: 静态申请

静态申请可以过poj注意初始化数组和数组大小

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long LL;
const int N=100000+999;
int flag,cot;
struct sky //这个代码跟上面那个除了申请内存方式不一样别的都一样
{
    int path;
    int ch;
    int end;
    sky *next[10];
    sky(char ch=' ')
    {
        this -> ch =ch;
        this -> path =this -> end =0;
        for(int i=0; i<10; i++)
            this -> next[i] = NULL; //在POJ好像不能用nullptr总是编译错误
    }
};
sky *root;
sky a[N];//注意数组大小
sky* new_sky() //用来分配已经申请好的内存空间
{
    return &a[cot++];
}
int add(char *s)
{
    sky *t=root;
    while(*s)
    {
        int i=*s-'0';
        if(t->next[i]==NULL)
            t->next[i] = new_sky();
        t->next[i]->path++;
        t=t->next[i];
        s++;
        if(t->end>0)
            return 1;
    }
    t->end++;
    if(t->path>1) return 1;
    return 0;
}

int main()
{
    int t,n;
    char num[13];
    scanf("%d",&t);
    while(t--)
    {
        cot=0;//记得初始化 啊
        root=new_sky(); //申请内存空间
        scanf("%d",&n);
        flag=0;
        while(n--)
        {
            scanf(" %s",num);
            flag=add(num);
            if(flag) break;
        }
        if(n>0)
        {
            while(n--)
                scanf(" %s",num);
        }
        if(flag) printf("NO\n");
        else printf("YES\n");
        memset(a,0,sizeof(a)); //清空内存空间。
    }
    return 0;
}




    

你可能感兴趣的:(字典树)