题目信息
前缀码:任何一个字符的编码都不是同一字符集中另一个字符的编码的前缀。
请编写一个程序,判断输入的n个由1和0组成的编码是否为前缀码。如果这n个编码是前缀码,则输出"YES”;否则输出第一个与前面编码发生矛盾的编码。
输入
第1行为n(表示下面有n行编码)
第2~n+1行为n个由0或1组成的编码
输出
判断结果
测试样例
测试样例1
5
00
01
10
110
111
YES
测试样例2
5
00
01
10
110
11
11
测试样例3
5
00
01
10
11
111
111
测试样例4
5
111
110
10
01
00
YES
测试样例5
8
00
010
0110
0111
10
110
1110
1111
YES
测试样例6
8
00
010
0110
0111
10
11
1110
111
1110
解答
#include <iostream>
using namespace std;
struct BtreeNode
{
bool data;//如果此处是终点放置标记为true
BtreeNode *Left;
BtreeNode *Right;
};
int main()
{
//freopen("/Users/zhj/Downloads/test.txt", "r", stdin);
int N;
cin >> N;
BtreeNode *Root = new BtreeNode;
Root->data = false;
Root->Left = NULL;
Root->Right = NULL;
while (N--)
{
string str;
cin >> str;
int len = str.length();
BtreeNode *p = Root;
for (int i = 0; i < len; i++)
{
if (str[i] == '0')
{//左边默认设置为0
if (p->Left == NULL)
{//左边是空的话就要为左边开辟相应的空间
p->Left = new BtreeNode;
p = p->Left;
p->Left = NULL;
p->Right = NULL;
if (i == len - 1)
{//读到最后一个字符
p->data = true;//将在此停止的放置标记为true
}
else
{//将路上遍历过的节点都设置成为0
p->data = false;
}
}
else
{//左边不空,说明已经建立好了这个节点,
if (i == len - 1 || p->Left->data)//不是空的又恰好在这里停止,说明你就是别人的前缀,或者是你遇到了别人截止的地方
{//如果恰好读到最后一个节点或者是data为1说明有人在这里停止,说明有重复
cout << str << endl;
return 0;
}
else
{
p = p->Left;
}
}
}
else
{
if (p->Right == NULL)
{
p->Right = new BtreeNode;
p = p->Right;
p->Left = NULL;
p->Right = NULL;
if (i == len - 1)
{
p->data = true;
}
else
{
p->data = false;
}
}
else
{
if (i == len - 1 || p->Right->data)
{
cout << str << endl;
return 0;
}
else
{
p = p->Right;
}
}
}
}
}
cout << "YES" << endl;
return 0;
}
想法
本题的精髓在于构建哈夫曼树来判定是否有重复的二叉树路径
哈夫曼树构建