7-1 Huffman Codes (30 分)(谷歌翻译的)
1953年,David A. Huffman发表了他的论文“构建最小冗余码的方法”,因此在计算机科学史上印刷了他的名字。作为给霍夫曼代码提出期末考试问题的教授,我遇到了一个大问题:霍夫曼代码并不是唯一的。例如,给定一个字符串“aaaxuaxz”,我们可以观察到字符“a”,“x”,“u”和“z”的频率分别为4,2,1和1。我们可以将符号编码为{'a'= 0,'x'= 10,'u'= 110,'z'= 111},或者换句话为{'a'= 1,'x'= 01 ,'u'= 001,'z'= 000},都将字符串压缩为14位。另一组代码可以给出{'a'= 0,'x'= 11,'u'= 100,'z'= 101},但{'a'= 0,
输入规格:
每个输入文件包含一个测试用例。对于每种情况,第一行给出一个整数N(2 ≤ Ñ ≤ 6 3),再其次是一个包含所有的线N个不同的字符及其频率采用以下格式:
c[1] f[1] c[2] f[2] ... c[N] f[N]
其中c[i]
是从{'0' - '9','a' - 'z','A' - 'Z','_'}中选择的字符,并且f[i]
是c[i]
并且是不超过1000的整数的频率。下一行给出正整数M(≤ 1 0 0 0),则接着M学生提交。每个学生提交的内容包括N行,每行格式:
c[i] code[i]
其中c[i]
是i
-th字符,code[i]
是一个非空字符串,不超过63'0和'1'。
输出规格:
对于每个测试用例,如果学生的提交正确,则在每行打印“是”,否则打印“否”。
注意:最优解不一定是由霍夫曼算法生成的。任何代码长度最佳的前缀代码都被认为是正确的。
样本输入:
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
#include<stdio.h> #include<stdlib.h> #include<malloc.h> #include<string.h> typedef struct HFTNode { char Data; int Parent; int Lchild; int Rchild; int Weight; }HFTNode, *HFTree; typedef struct CNode { char Data; char Code[100]; }CNode; HFTree T; void AddNode(int N) { int min1 = 0, min2 = 0; for(int i=1; i<N; i++){//找到两个没父母的节点 if(T[i].Parent == 0 && min1 == 0) min1 = i; else if(T[i].Parent == 0 && min1 != 0) min2 = i; } if(T[min1].Weight > T[min2].Weight){ int temp = min1; min1 = min2; min2 = temp; } for(int i=1; i<N; i++){//找到两个没父母的最小节点 if(T[i].Parent == 0 && T[i].Weight < T[min1].Weight){ min2 = min1; min1 = i; } else if(T[i].Parent == 0 && T[i].Weight < T[min2].Weight && i!=min1 ) min2 = i; } T[N].Weight = T[min1].Weight + T[min2].Weight; T[N].Lchild = min1; T[N].Rchild = min2; T[N].Parent = 0; T[min1].Parent = N; T[min2].Parent = N; } int JuChild(int m1, int m2, CNode *Code) { int len = strlen(Code[m1].Code); int flag = 0; for(int i=0; i<len; i++){ if(Code[m1].Code[i] != Code[m2].Code[i])//存在不相等的则赋1 flag = 1; } if(flag == 0)//说明是子序列 return 1; else return 0; } int main() { int N, M, Weight=0; scanf("%d", &N);getchar(); T = (HFTNode*)malloc(sizeof(HFTNode)*(2*N)); for(int i=1; i<=N; i++){ scanf("%c %d", &T[i].Data, &T[i].Weight);getchar(); T[i].Parent = 0; T[i].Lchild = 0; T[i].Rchild = 0; } for(int i=N+1; i<2*N; i++){//带权路径为非叶节点权值之和 AddNode(i); Weight += T[i].Weight; } scanf("%d", &M); for(int i=0; i<M; i++){ CNode Code[100]; int weight = 0; for(int j=1; j<=N; j++){ scanf("%c%*c%s", &Code[j].Data, &Code[j].Code); weight += T[j].Weight * strlen(Code[j].Code); } if(weight != Weight)//带权路径不一致 printf("No "); else{ int flag = 1; for(int j=N; j>=1 && flag; j--){//判断某个序列是否是另一个编码的子序列 for(int i=1; i<j; i++){ int is = JuChild(j, i, Code); if(is){ printf("No "); flag = 0; break; } } } if(flag) printf("Yes "); } } }