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 <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <queue>
#include <vector>
#include <map>
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 <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <queue>
#include <vector>
#include <map>
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;
}




    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值