二十一、前缀码判定

二十一、前缀码判定

题目描述

前缀码:任何一个字符的编码都不是同一字符集中另一个字符的编码的前缀。

请编写一个程序,判断输入的n个由1和0组成的编码是否为前缀码。如果这n个编码是前缀码,则输出"YES”;否则输出第一个与前面编码发生矛盾的编码。

输入:
第1行为n(表示下面有n行编码)
第2~n+1行为n个由0或1组成的编码

**输出:**判断结果

例如,如果输入:

5

00

01

10

110

111

每一个字符均不是其他字符编码的前缀,所以,输出:YES

再如,如果输入:

5

00

01

10

110

11

编码11与前面的编码110的前缀,所以,输出:11

测试输入期待的输出时间限制内存限制额外进程
测试用例 15
00
01
10
110
111
YES1秒64M0
测试用例 25
00
01
10
110
11
111秒64M0
测试用例 35
00
01
10
11
111
1111秒64M0
测试用例 45
111
110
10
01
00
YES1秒64M0
测试用例 58
00
010
0110
0111
10
110
1110
1111
YES1秒64M0
测试用例 68
00
010
0110
0111
10
11
1110
111
11101秒64M0

解题思路

所谓前缀码的判定,本质上是二叉树的建树问题。令二叉树的左子树都代表1,遇到 1 都向左走;右子树都代表0,遇到 0 都向右走。

对于全新的没有前缀的字符编码,则二叉树中建立对应分支,分支除了最后一个结点外的所有结点值都为0,仅最后一个结点值为1。

字符编码是前缀码的话,如果在分支的行进过程中碰到值为 1 的结点,则当前字符编码存在前缀码;如果编码遍历完成,但是最后一个字符没有新建结点,则当前字符编码是别人的前缀码。

对于前缀码,我们用一个 flag 进行标记。当 flag 为 1 时表示存在前缀码,输出第一个前缀码 prefix。如果全部判断完成,flag 仍为0,则没有前缀码。

上机代码

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
typedef struct NODE
{
	int data;
	struct NODE *lchild;
	struct NODE *rchild;
}node,*Tree;

int main()
{
	int n = 0;
	char str[100010], prefix[100010];
	int flag = 0;
	
	Tree bit, T;
	bit = (Tree)malloc(sizeof(node));//初始化
	bit->data = 0;
	bit->lchild = NULL;
	bit->rchild = NULL;

	cin >> n;
	while(n--)
	{
		memset(str, 0, sizeof(str));
		cin >> str;
		int len = strlen(str);

		if (flag == 1)	//存在前缀码后面都不用判断了,读取编码后直接跳出循环
			continue;
		strcpy(prefix, str);//保存第一个前缀码

		T = bit;//每次变回根节点初始化状态
		for (int i = 0; i < len; i++)
		{
			if (str[i] == '1')	//1向左走
			{
				if (T->lchild == NULL)//左子树新建结点
				{
					T->lchild = (Tree)malloc(sizeof(node));
					T = T->lchild;
					T->lchild = NULL;
					T->rchild = NULL;
					if (i == len - 1)
						T->data = 1;
					else
						T->data = 0;
				}
				else
				{
					if (T->lchild->data == 1 || i == len - 1)//存在前缀码
					{
						flag = 1;
						break;
					}
					else
						T = T->lchild;
				}
			}
			else	//0向右走
			{
				if (T->rchild == NULL)//右子树新建结点
				{
					T->rchild = (Tree)malloc(sizeof(node));
					T = T->rchild;
					T->lchild = NULL;
					T->rchild = NULL;
					if (i == len - 1)
						T->data = 1;
					else
						T->data = 0;
				}
				else
				{
					if (T->rchild->data == 1 || i == len - 1)
					{
						flag = 1;
						break;
					}
					else
						T = T->rchild;
				}
			}
		}
	}
	if (flag == 0)//没有前缀码
		cout << "YES" << endl;
	else
		cout << prefix << endl;
	//system("pause");
	return 0;
}
  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值