HDU1671【Tire】

博客分析了一道HDU1671的题目,探讨如何确保数据集中没有任何数据是其他数据的前缀,从而避免特定的数据序列出现。
摘要由CSDN通过智能技术生成

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

【分析】这个题目意识是在这一组数据中不出现某个数据作为某个数据的前缀。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Tire      //建立一个结点的结构体
{ 
	int end;                  //判断是否是一个单词的终点
	struct Tire *child[11];    //10个分支结点
}tree;
tree *root;                //定义一个Tire的指针
int flag;                    //判断这组数据是否出现某个电话是另一个电话的前缀
void insert(char *s)            //插入这个单词并判断①这个单词是否会成为别的单词的前缀 
                              //判断②是否有别的单词成为这个单词的前缀
{ 
	int i, j;
	int len = strlen(s);
	tree *a = root;                     
	for (i = 0; i<len; i++)
	{
		int k = s[i] - '0';
		if (a->child[k] != NULL)    //一个数字一个数字查找,如果发现该数字后面的节点不为空,证明他后面的这个孩子分支存在。
		{
			a = a->child[k];       //将a的指针指向这个孩子分支
			if (a->end == 1)       //判断②如果这个节点的end标记为1,代表有某个号码成为这个号码的前缀。
			{
				flag = 1;           //flag==1,代表要输出NO,直接退出循环
				return;
			}
		}
		else
		{
			tree *temp = (tree*)malloc(sizeof(tree));// 为temp申请动态内存
			a->child[k] = temp;               //将a的下一层节点k位置 指向temp,a的temp孩子不是空的,但是temp的孩子分支都是空的;
			for (j = 0; j<10; j++)
				temp->child[j] = NULL;
			a = temp;
		}
	}
	a->end = true;                        // 将该数串最后一个节点的 标记变量置为true;
	for (int i = 0; i<10; i++)
	{
		if (a->child[i] != NULL)            //判断①,证明这个号码成为了别的号码的前缀,
		{
			flag = 1;
			return;
		}
	}
}
void end(struct Tire *p)   //释放内存
{
	int i;
	for (i = 0; i<10; i++)
		if (p->child[i] != NULL) end(p->child[i]);
	delete(p);
}
int main()
{
	int t;
	scanf("%d", &t);
	char s[10005];
	while (t--)
	{
		root = (tree*)malloc(sizeof(tree));//申请内存
		for (int i = 0; i<10; i++)
			root->child[i] = NULL;
		flag = 0;                         //初始化这组数据未发现问题
		int n;
		scanf("%d", &n);
		for (int i = 0; i<n; i++)
		{
			scanf("%s", s);
			insert(s);
		}
		if (flag)
			printf("NO\n");
		else
			printf("YES\n");
		end(root);     //每一次都必须要释放内存,否则会MTL 
	}
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值