In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redundancy Codes", and hence printed his name in the history of computer science. As a professor who gives the final exam problem on Huffman codes, I am encountering a big problem: the Huffman codes are NOT unique. For example, given a string "aaaxuaxz", we can observe that the frequencies of the characters 'a', 'x', 'u' and 'z' are 4, 2, 1 and 1, respectively. We may either encode the symbols as {'a'=0, 'x'=10, 'u'=110, 'z'=111}, or in another way as {'a'=1, 'x'=01, 'u'=001, 'z'=000}, both compress the string into 14 bits. Another set of code can be given as {'a'=0, 'x'=11, 'u'=100, 'z'=101}, but {'a'=0, 'x'=01, 'u'=011, 'z'=001} is NOT correct since "aaaxuaxz" and "aazuaxax" can both be decoded from the code 00001011001001. The students are submitting all kinds of codes, and I need a computer program to help me determine which ones are correct and which ones are not.
Input Specification:
Each input file contains one test case. For each case, the first line gives an integer N (2≤N≤63), then followed by a line that contains all the N distinct characters and their frequencies in the following format:
c[1] f[1] c[2] f[2] ... c[N] f[N]
where c[i]
is a character chosen from {'0' - '9', 'a' - 'z', 'A' - 'Z', '_'}, and f[i]
is the frequency of c[i]
and is an integer no more than 1000. The next line gives a positive integer M (≤1000), then followed by M student submissions. Each student submission consists of N lines, each in the format:
c[i] code[i]
where c[i]
is the i
-th character and code[i]
is an non-empty string of no more than 63 '0's and '1's.
Output Specification:
For each test case, print in each line either "Yes" if the student's submission is correct, or "No" if not.
Note: The optimal solution is not necessarily generated by Huffman algorithm. Any prefix code with code length being optimal is considered correct.
Sample Input:
7
A 1 B 1 C 1 D 3 E 3 F 6 G 6
4
A 00000
B 00001
C 0001
D 001
E 01
F 10
G 11
A 01010
B 01011
C 0100
D 011
E 10
F 11
G 00
A 000
B 001
C 010
D 011
E 100
F 101
G 110
A 00000
B 00001
C 0001
D 001
E 00
F 10
G 11
Sample Output:
Yes
Yes
No
No
#include<stdio.h>
#include<stdlib.h>
#define Maxsize 63
typedef struct node {
int n;
char s;
struct node * left;
struct node * right;
}Node;
typedef struct nodes {
Node *A;
}Nodes,*qNodes;
typedef struct tree {
int N;
char S;
struct tree * left;
struct tree * right;
}Tree,*qTree;
//构造堆
void Create(qNodes *a,int length) {
*a = (Nodes *)malloc(sizeof(Nodes));
(*a)->A = (Node *)malloc(sizeof(Node)*(length+1));
(*a)->A[0].n = -1;
(*a)->A[0].s = '*';
(*a)->A[0].left = NULL;
(*a)->A[0].right = NULL;
}
//小顶堆排序
void Sort(qNodes *a,int length) {
for (int i = length; i >0; i--) {
int j = i;
while (j!=1)
{
if ((*a)->A[j].n < (*a)->A[j / 2].n) {
int temp = (*a)->A[j].n;
char tep = (*a)->A[j].s;
(*a)->A[j].n = (*a)->A[j / 2].n;
(*a)->A[j].s = (*a)->A[j / 2].s;
(*a)->A[j / 2].n = temp;
(*a)->A[j / 2].s = tep;
}
j /= 2;
}
}
}
//插入堆
void Insert(qNodes *q, Node *N,int length) {
length++;
//(*q)->A[length].n = N->n;
//(*q)->A[length].s = N->s;
while (length>1)
{
if (N->n < (*q)->A[length / 2].n) {
(*q)->A[length].n = (*q)->A[length / 2].n;
(*q)->A[length].s = (*q)->A[length / 2].s;
(*q)->A[length].left = (*q)->A[length / 2].left;
(*q)->A[length].right = (*q)->A[length / 2].right;
}
else {
break;
}
length /= 2;
}
(*q)->A[length].n = N->n;
(*q)->A[length].s = N->s;
(*q)->A[length].left = N->left;
(*q)->A[length].right = N->right;
}
//弹出根节点
Node * Pop(qNodes *q,int length) {
int len = length;
length--;
Node *p = (Node *)malloc(sizeof(Node));
p->n = (*q)->A[1].n;
p->s = (*q)->A[1].s;
p->right = (*q)->A[1].right;
p->left = (*q)->A[1].left;
int i = 1;
//(*q)->A[1].n = (*q)->A[length].n;
//(*q)->A[1].s = (*q)->A[length].s;
while (i*2<=length)
{ //有右子树存在且右子树更小
if (2*i!=length&&(*q)->A[2*i].n> (*q)->A[2*i + 1].n) {
i = 2 * i + 1;
}
else {
i *= 2;
}
if ((*q)->A[i].n < (*q)->A[len].n) { //更小的往上移动
(*q)->A[i / 2].n = (*q)->A[i].n;
(*q)->A[i / 2].s = (*q)->A[i].s;
(*q)->A[i / 2].right = (*q)->A[i].right;
(*q)->A[i / 2].left = (*q)->A[i].left;
}
else {
i /= 2;
break;
}
}//尾节点放入适合位置
(*q)->A[i].n = (*q)->A[len].n;
(*q)->A[i].s = (*q)->A[len].s;
(*q)->A[i].left = (*q)->A[len].left;
(*q)->A[i].right = (*q)->A[len].right;
return p;
}
//构建哈希排序树
Node* CreatTree(qNodes q, int length) {
Node *N=NULL;
while (length > 1) {
Node *t = (Node *)malloc(sizeof(Node));
Node *L = Pop(&q, length);
length--;
Node *R = Pop(&q, length);
length--;
t->n = L->n + R->n;
t->left = L;
t->right = R;
t->s = '*';
N = t; //N保存树根
Insert(&q, t, length);
length++;
}
return N;
}
int PanDuan(qTree tr) {
if (tr->S != '*') {
if (tr->right == NULL && tr->left == NULL) {
return 1;
}
else {
return 0;
}
}
if (tr->S == '*') {
if (tr->left != NULL && tr->right!= NULL) {
return PanDuan(tr->right) && PanDuan(tr->left);
}
else {
return 0;
}
}
}
int QiuHe(qTree tr,int hight) {
if (tr->S != '*') {
return tr->N*hight;
}
else {
return QiuHe(tr->left, hight+1) + QiuHe(tr->right, hight+1);
}
}
int He(Node tr, int hight) {
if (tr.s != '*') {
return tr.n*hight;
}
else {
return He(*tr.left, hight + 1) + He(*tr.right, hight + 1);
}
}
int main()
{
int N = 0;
scanf("%d\n", &N);
qNodes a=NULL;
Create(&a,N);
int n;
char s;
for (int i = 1; i < N; i++) {
scanf("%c ", &s);
scanf("%d ", &n);
a->A[i].s = s;
a->A[i].n = n;
a->A[i].left = NULL;
a->A[i].right = NULL;
}
scanf("%c ", &s);
scanf("%d", &n);
a->A[N].s = s;
a->A[N].n = n;
a->A[N].left = NULL;
a->A[N].right = NULL;
Sort(&a, N);
qNodes b= NULL;
Create(&b, N);
for (int i = 1; i <= N; i++) {
b->A[i].s = a->A[i].s;
b->A[i].n = a->A[i].n;
b->A[i].left = a->A[i].left;
b->A[i].right = a->A[i].right;
}
//构建哈希排序树
Node *Z = CreatTree(a, N);
int pep = 0, length = 0;;
scanf("%d\n", &pep);
char C1='*', *C2=NULL;
C2 = (char*)malloc(sizeof(char) * 64);
for (int k = 0; k < pep; k++) {
qTree tree = (Tree *)malloc(sizeof(Tree));
tree->left = NULL;
tree->right = NULL;
tree->S = '*';
tree->N = 0;
for (int i = 0; i < N; i++) {
scanf("%c ", &C1);
gets(C2);
qTree pre = tree;
int j = 0;
do
{
if (C2[j] == '0') {
if (pre->left == NULL) {
qTree pp = (Tree *)malloc(sizeof(Tree));
pp->left = NULL;
pp->right = NULL;
pp->S = '*';
pp->N = 0;
pre->left = pp;
}
pre = pre->left;
}
else {
if (pre->right == NULL) {
qTree pp = (Tree *)malloc(sizeof(Tree));
pp->left = NULL;
pp->right = NULL;
pp->S = '*';
pp->N = 0;
pre->right = pp;
}
pre = pre->right;
}
j++;
} while (C2[j] != '\0');
pre->S = C1;
for (int m = 1; m <= N; m++) {
if (b->A[m].s == C1) {
pre->N = b->A[m].n;
break;
}
}
}
int flag = PanDuan(tree);
int count = 0, count1 = 0;;
if (flag==1)
{
count = QiuHe(tree,0);
count1 = He(*Z,0);
if (count == count1) {
printf("Yes");
}else {
printf("No");
}
}
else {
printf("No");
}
if (k != pep - 1) {
printf("\n");
}
free(tree);
tree = NULL;
}
if (pep <= 0) {
printf("No");
}
return 0;
}