HDU 1305 Immediate Decodability HDU 1671 Phone List(字典树)

19 篇文章 0 订阅
5 篇文章 0 订阅

题目链接:

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

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

这两题几乎都是一样,所以就一起贴上来了...........

题意:

每个测试实例先输入一个数N1<=N<=10000),接着输入N个数字串。这些数字串作为电话号码,判断在拨号过程中是否出现干扰的号码,若有干扰的号码则不能打通输出NO,否则输出YES。干扰是这样理解的:一个串T,一个串S,不妨设lengthT<lengthS),如果TS的子串那么就产生干扰,因为假如我要拨S号码,那么我在拨完S号码前一定已经把T号码给拨完了,那么电话就转到T上了。

用字典树先保存所有数据,那么据题意判断是否产生干扰就看每个节点的num值与它的所有存在的子节点的num值之和是否相等,如果不相等那么必然有干扰了。

如果字符串Xn=X1X2....Xn是字符串Ym=Y1Y2....Ym的前缀,有在插入的时候有两种情况:XnYn之前插入,XnYn之后插入。

 (1)如果Xn在Yn之前插入,那么在插入Yn的时候必然经过Xn的路径,此时可以根据判断在这条路径上是否已经有结点被标记已经构成完成的字符串序列来判断是否存在Yn的前缀;

(2)如果Xn在Yn之后插入,那么插入完成之后当前指针指向的结点的next数组中的元素必定不全为NULL。
HDU 1671 AC code:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
bool is_phone;/*判断是否能成功拨打号码*/
struct node
{
    bool flag;/*在数字串最后标记*/
    struct node *next[10];
};
struct node *root;
struct node *newset()/*新建结点*/
{
    struct node *p=(struct node *)malloc(sizeof(struct node));
    for(int i=0;i<10;i++)
    {
        p->next[i]=NULL;
    }
    p->flag=false;/*初始化为false*/
    return p;
}
void insert(char *str)/*建立字典树*/
{
    struct node *p;
    p=root;
    int len=strlen(str);
    for(int i=0;i<len;i++)
    {
        if(p->next[str[i]-'0']==NULL)/*如果以前没有建立过该结点*/
        {
           if(p->flag==false)
           {
			   p->next[str[i]-'0']=newset();/*建立新结点*/
			   p=p->next[str[i]-'0'];
               if(i==len-1)/*只有当指向到数字串末尾时,标记结点为true;*/
               {
                   p->flag=true;
               }
               else
               {
                   p->flag=false;
               }
           }
           else/*否则说明当前建立的数字串覆盖了以前的数字串(当前更长),不能拨打号码*/
           {
               is_phone=false;
               return ;
               
           }
        }
        else
        {
            if(i==len-1&&p->flag==false)/*如果当前号码是以前出现过的号码的前缀(当前更短)*/
            {
                is_phone=false;
                return ;
            }
            p=p->next[str[i]-'0'];
        }
    }
    return ;
}
int del(node *t)/*释放内存*/
{
    if(t==NULL) return 0;
    for(int i=0;i<10;i++)
    {
        if(t->next[i]!=NULL)
        {
            del(t->next[i]);
        }
    }
    free(t);
    return 0;
}
int main()
{
    int ncase,n;
    char str[1001];
    scanf("%d", &ncase);
    while(ncase--)
    {
        root=newset();
        scanf("%d",&n);
        is_phone=true;
        for(int i=0;i<n;i++)
        {
            scanf("%s",str);
            insert(str);
        }
        if(is_phone) printf("YES\n");
        else printf("NO\n");
        del(root);
    }
    return 0;
}        

1305 AC code:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
bool is_phone;/*判断是否能成功拨打号码*/
struct node
{
    bool flag;/*在数字串最后标记*/
    struct node *next[10];
};
struct node *root;
struct node *newset()/*新建结点*/
{
    struct node *p=(struct node *)malloc(sizeof(struct node));
    for(int i=0;i<10;i++)
    {
        p->next[i]=NULL;
    }
    p->flag=false;/*初始化为false*/
    return p;
}
void insert(char *str)/*建立字典树*/
{
    struct node *p;
    p=root;
    int len=strlen(str);
    for(int i=0;i<len;i++)
    {
        if(p->next[str[i]-'0']==NULL)/*如果以前没有建立过该结点*/
        {
           if(p->flag==false)
           {
			   p->next[str[i]-'0']=newset();/*建立新结点*/
			   p=p->next[str[i]-'0'];
               if(i==len-1)/*只有当指向到数字串末尾时,标记结点为true;*/
               {
                   p->flag=true;
               }
               else
               {
                   p->flag=false;
               }
           }
           else/*否则说明当前建立的数字串覆盖了以前的数字串(当前更长),不能拨打号码*/
           {
               is_phone=false;
               return ;
           }
        }
        else
        {
            if(i==len-1&&p->flag==false)/*如果当前号码是以前出现过的号码的前缀(当前更短)*/
            {
                is_phone=false;
                return ;
            }
            p=p->next[str[i]-'0'];
        }
    }
    return ;
}
int del(node *t)
{
    if(t==NULL) return 0;
    for(int i=0;i<10;i++)
    {
        if(t->next[i]!=NULL)
        {
            del(t->next[i]);
        }
    }
    free(t);
    return 0;
}
int main()
{
    int num(1);
    char str[1001];
    while(~scanf("%s",str))
    {
		root=newset();
		is_phone=true;
		insert(str);
		while(scanf("%s",str),*str!='9')
		{
			insert(str);
		}
		if(is_phone) printf("Set %d is immediately decodable\n",num++);
        else printf("Set %d is not immediately decodable\n",num++);
	}
    return 0;
}


 








  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值