【POJ 3630】Phone List 中文题意&题解&代码(C++)

这是一个关于POJ 3630问题的博客,主要讨论如何判断一个电话号码列表是否一致,即没有号码是另一个号码的前缀。博客提供了问题描述、输入输出示例,并指出使用字典树作为解决问题的有效方法。通过字典树在构建过程中进行检查,最终得出结论并输出结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Phone List

Time Limit: 1000MS Memory Limit: 65536K

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。


题解:
按数据来看,用字典树来处理是一个很好的做法,在建字典树的过程中,特殊判断一下,最后输出。


#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
using namespace std;
struct node{
    int ch[10];
    void init()
    {
        for (int i=0;i<10;i++)
        ch[i]=0;
    }
    bool pan()//判断这是否是一个已有字符串的终点
    {
        for (int i=0;i<10;i++)
        if (ch[i]!=0) return 1;
        return 0;
    }
}tr[1000005*12];
char s[1000005];
int p=0,tot=0,len,n,t,flag[1000005];
void add(int id)
{
    int now=0;
    for (int i=0;i<len;i++)
    {
        int tmp=s[i]-'0';

        if (now!=0 && flag[now]!=id && (tr[now].pan()==0))
        p=-1; 
        //判断之前已经加入字典树的那些数串是否是此次加入字符串的前缀
        //感觉自己想的这个方法有点sb可以去别人的博客参考一下
        //有没有更好的判断方法
        if (!tr[now].ch[tmp])
        {
            tot++;
            tr[now].ch[tmp]=tot;
            tr[tot].init();
            flag[tot]=id;
        }
        now=tr[now].ch[tmp];
    }
    if (flag[now]!=id) p=-1;
}
int main()
{
    scanf("%d",&t);
    for (int w=1;w<=t;w++)
    {
        tot=0;
        p=0;
        tr[tot].init();
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            scanf("%s",s);
            len=strlen(s);
            if (p==0)
            add(i);
        }
        if (p==-1) printf("NO\n");
        else printf("YES\n");
    }
}

还有题上没给字符串的长度范围,坑的我re两次。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值