HDU 1671 Phone List (字典树入门)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1671


题面:

Phone List

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 15029    Accepted Submission(s): 5064


Problem 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:
1. Emergency 911
2. Alice 97 625 999
3. 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”。


解题:

    构造字典树,然后查询每一条电话号码,一旦发现以某号码结尾的位置,该点val值大于1,输出NO。


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct Trie
{
	//ch数组存储每个节点的10个数字分别对应节点编号,没有为0,根节点为0
	//小心 
	//第一维要乘以10,因为一个节点一个数字 
	int ch[100010][10];
	//val数组一般用来存储权值,视题目灵活运用,sz是当前节点数量
	int val[100010],sz;
	//初始化
	void init()
	{
		sz=1;
		memset(ch,0,sizeof(ch));
	}
	//插入一条单词
	void insert(char *s)
	{
		//u是节点编号,并不是层数
		int u=0,len=strlen(s);
		for(int i=0;i<len;i++)
		{
			//取下标
			int c=(s[i]-'0');
			//如果该节点不存在,创建该节点
			if(!ch[u][c])
			{
				//真的是相当的省
				memset(ch[sz],0,sizeof(ch[sz]));
				//因为刚创建所以为1
				val[sz]=1;
				//给该节点分配编号
				ch[u][c]=sz++;
				//下移
				u=ch[u][c];
			}
			//已经存在了
			else
			{
			  //下移,并计数值加一
			  u=ch[u][c];
		      val[u]++;
			}
		}
	}
	//查询前缀
	bool query(char *s)
	{
		int len=strlen(s),u=0,c;
		//不断下移,直至移到给定的前缀的最后一个单词
		for(int i=0;i<len;i++)
		{
		   c=s[i]-'0';
           u=ch[u][c];
		}
        if(val[u]>1)
           return true;
        else
          return false;
	}
};
Trie T;
char store[10010][12];
int main()
{
    int n,t;
	scanf("%d",&t);
	bool flag=true;
	for(int i=1;i<=t;i++)
	{
	    flag=true;
		scanf("%d",&n);
		T.init();
        for(int j=0;j<n;j++)
		{
			getchar();
			scanf("%s",store[j]);
			T.insert(store[j]);
		}
        for(int j=0;j<n;j++)
        {
            if(T.query(store[j]))
            {
                flag=false;
                break;
            }
        }
        if(flag)
          printf("YES\n");
        else
          printf("NO\n");
	}
	return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值