POJ 3630:Phone List(字典树入门)

题目链接:http://poj.org/problem?id=3630

题目意思:

如果拨打的电话号码的前缀是一个完整的电话号码,则这个电话就不能拨通,判断给出的电话列表是否全部能拨通。

这个题目只用再建立字典树的过程中做判断就行了,没必要建完之后再去查询,我们可以在节点设置count统计某个

节点所代表的单词当前称为别人前缀的次数。再用个bool变量记录当前节点所代表的一串字符是不是一个完整的电话

号码,当一个字符串是完整的电话号码,且被已经加入的串当作前缀两次,这列电话号码就不能全部拨通。


坑点:

1.不能是用动态链表,malloc动态分配内存提交会超时,这个题目得用静态链表。

2.静态链表数组开到一两万过不去,尽量开大点,我直接开10万过了。


AC代码:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

const int maxn = 10;   
char telNum[10002][14];
struct TrieNode
{
    bool isCompleteTel;
    int ccount;
    struct TrieNode *son[maxn];
}node[100000];
int num;
TrieNode* createNode()
{
   TrieNode *p = &node[num++];
   for(int i = 0; i < maxn; i++)
   {
       p->son[i] = NULL;
   }
   return p;
}
///边插入Telphone边判断。不用建玩树后再去一个个判断。
bool insertTel(TrieNode *root,char tel[])
{
    TrieNode *p;
    p = root;
    int i = 0;
    char ch = tel[i];
    while(ch != '\0')
    {
        if(p->son[ch-'0'] == NULL)
        {

            p->son[ch-'0'] = createNode();
            p = p->son[ch-'0'];
            p->isCompleteTel = false;
            p->ccount = 1;
        }
        else
        {
            p->son[ch-'0']->ccount++;
            p = p->son[ch-'0'];
            if(p->ccount>1 && p->isCompleteTel==true)  ///如果有一串完整电话号码已经到过这里了。就不能拨打成功。
                return false;
        }
        ch = tel[++i];
    }
    p->isCompleteTel = true;
    if(p->ccount>1 && p->isCompleteTel==true)  ///曾经有电话号码的前缀到达过这个电话号码的结尾了,也不行。
        return false;
    return true;
}
int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        num = 0;
        scanf("%d",&n);
        bool OK = true;
        TrieNode *root = createNode();
        for(int i = 0; i < n; i++)
        {
            scanf("%s",telNum[i]);
            if(OK)
            {
                OK = insertTel(root,telNum[i]);
            }
        }
        if(OK)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值