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.
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.
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.
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
Yes
Yes
No
No
就是检查学生输入的编码是否合理,一是WPL合理,二是前缀码,不是哈夫曼编码也可以。
由两方面进行判断:WPL长度和是否是前缀码。
一开始没弄清前缀码是啥就直接对提交编码进行字符串方面的比较…后面提交只有一个测试点通过才去查了定义,草。
检查编码是否是前缀码的方法是根据编码建一棵二叉树,建二叉树的时候会遍历各个节点,当遍历经过了某个节点是另一段编码的终点,就说明那段编码是这段正在遍历的编码的前缀(难以表述,意会就好)
#include
#include
#include
#pragma warning(disable:4996)
#define MAXN 65
typedef struct HaffCode *PtrH;
typedef struct Min_Heap *PtrM;
typedef struct Submit *PtrS;
typedef struct OrigData *PtrO;
typedef struct JNode *PtrJ;
struct HaffCode
{
char rep;
int wei;
PtrH right, left;
};
struct Min_Heap
{
int size;
int cap;
PtrH Elems[MAXN];
};
struct Submit
{
char rep;
char code[MAXN];
int length;
};
struct OrigData
{
char rep;
int weight;
};
struct JNode
{
int flag;
PtrJ left;
PtrJ right;
};
void Insert(PtrM M, PtrH item);
PtrH Delete(PtrM M);
PtrM Create(int maxsize);
void Establish(PtrM M,PtrO Orig);
void PercDown(PtrM M, int index);
PtrH Huffman(PtrM M);
int WPL(PtrH H, int height);
void Print(PtrH H);
void Check(int WPL, int N, PtrO Orig);
int FindWeight(PtrO Orig, char rep,int N);
PtrJ NewNode(void);
int Judge(char *s, PtrJ J);
int main()
{
PtrM M;
PtrH H;
OrigData Orig[MAXN];
int N, wpl, weight[MAXN];
scanf("%d\n", &N);
M = Create(N);
Establish(M,Orig);
H = Huffman(M);
wpl = WPL(H, 0);
Check(wpl, N, Orig);
system("pause");
return 0;
}
void Insert(PtrM M, PtrH item)
{
int i;
i = ++M->size;
for (; M->Elems[i / 2]->wei >= item->wei; i /= 2)
M->Elems[i] = M->Elems[i / 2];
M->Elems[i] = item;
}
PtrH Delete(PtrM M)
{
int Parent, Child;
PtrH Minitem, temp;
Minitem = M->Elems[1];
temp = M->Elems[M->size--];
for (Parent = 1; Parent * 2 <= M->size; Parent = Child)
{
Child = Parent * 2;
if ((Child != M->size) && (M->Elems[Child]->wei > M->Elems[Child + 1]->wei))
Child++;
if (temp->wei <= M->Elems[Child]->wei)
break;
else M->Elems[Parent] = M->Elems[Child];
}
M->Elems[Parent] = temp;
return Minitem;
}
PtrM Create(int maxsize)
{
PtrM M;
M = (PtrM)malloc(sizeof(struct Min_Heap));
M->cap = maxsize;
M->Elems[0] = (PtrH)malloc(sizeof(struct HaffCode));
M->size = 0;
M->Elems[0]->wei = -1;
M->Elems[0]->rep = -1;
M->Elems[0]->left = M->Elems[0]->right = NULL;
return M;
}
void Establish(PtrM M,PtrO Orig)
{
int i;
M->size = M->cap;
for (i = 1; i size; i++)
{
M->Elems[i] = (PtrH)malloc(sizeof(struct HaffCode));
scanf("%c%d ", &(M->Elems[i]->rep),&(M->Elems[i]->wei));
Orig[i-1].rep = M->Elems[i]->rep;
Orig[i-1].weight = M->Elems[i]->wei;
M->Elems[i]->right = M->Elems[i]->left = NULL;
}
M->Elems[i] = (PtrH)malloc(sizeof(struct HaffCode));
scanf("%c%d", &(M->Elems[i]->rep),&(M->Elems[i]->wei));
Orig[i - 1].rep = M->Elems[i]->rep;
Orig[i - 1].weight = M->Elems[i]->wei;
M->Elems[i]->right = M->Elems[i]->left = NULL;
for ( i = M->size / 2; i > 0; i--)
PercDown(M, i);
}
void PercDown(PtrM M, int index)
{
int Parent, Child;
PtrH H = M->Elems[index];
for (Parent = index; Parent * 2 <= M->size; Parent = Child)
{
Child = Parent * 2;;
if ((Child!=M->size)&&(M->Elems[Child]->wei > M->Elems[Child + 1]->wei))
Child++;
if (H->wei <= M->Elems[Child]->wei)
break;
else
M->Elems[Parent] = M->Elems[Child];
}
M->Elems[Parent] = H;
}
PtrH Huffman(PtrM M)
{
int i;
PtrH H;
for (i = 1; M->size>1; i++)
{
H = (PtrH)malloc(sizeof(struct HaffCode));
H->left = Delete(M);
H->right = Delete(M);
H->wei = H->left->wei + H->right->wei;
H->rep = -1;
Insert(M, H);
}
H = Delete(M);
return H;
}
int WPL(PtrH H, int height)
{
if (H->rep != -1)
return H->wei*height;
else return WPL(H->left, height + 1) + WPL(H->right, height + 1);
}
void Print(PtrH H)
{
if (H)
{
if (H->rep != -1)
printf("%c %d ", H->rep, H->wei);
Print(H->left);
Print(H->right);
}
}
void Check(int WPL, int N, PtrO Orig)
{
int M, SubW;
Submit Sub[MAXN];
scanf("%d", &M);
for (int i = 0; i < M; i++)
{
SubW = 0;
for (int j = 0; j < N; j++)
{
scanf("\n%c", &Sub[j].rep);
scanf(" %s", Sub[j].code);
Sub[j].length = strlen(Sub[j].code);
SubW += FindWeight(Orig, Sub[j].rep, N)*Sub[j].length;
}
if (SubW > WPL)
{
printf("No\n");
continue;
}
int k;
PtrJ J = NewNode();
for (k = 0; k < N; k++)
if (!Judge(Sub[k].code, J))
break;
if (k == N)
printf("Yes\n");
else printf("No\n");
}
}
int FindWeight(PtrO Orig, char rep,int N)
{
int i;
for (i = 0; i < N; i++)
if (Orig[i].rep == rep)
return Orig[i].weight;
printf("No found\n");
return -1;
}
PtrJ NewNode(void)
{
PtrJ J;
J = (PtrJ)malloc(sizeof(struct JNode));
J->flag = 0;
J->left = NULL;
J->right = NULL;
return J;
}
int Judge(char *s, PtrJ J)
{
int i, len;
len = strlen(s);
for (i = 0; i < len; i++)
{
if (s[i] == '0')
{
if (!J->left)
J->left = NewNode();
else if (J->left->flag)
return 0;
J = J->left;
}
else
{
if (!J->right)
J->right = NewNode();
else if (J->right->flag)
return 0;
J = J->right;
}
}
J->flag = 1;
if ((!J->left) && (!J->right))
return 1;
else return 0;
}
写的又臭又长…