问题 J: 赫夫曼编码
时间限制: 1 Sec 内存限制: 128 MB提交: 15 解决: 6
[ 提交][ 状态][ 讨论版]
题目描述
赫夫曼编码能够产生最短的报文。以报文“ABCDABCDABCABDABAA”为例,A编为0,B对应10,C对应110,D对应111,整体的报文长度为35位二进制。相比于定长的ASCII码,压缩比达到了18*8/35=4.1。
输入
输入有一系列的字符串组成,每个字符串占据一行。字符串仅包含大写字母和下划线。字符串“END” 表示处理结束,不应对其处理。
输出
对每一个字符串,输出其ASCII编码的比特位长度,赫夫曼编码的比特位长度,以及二者之比,精确到小数点后一位。
样例输入
ABCDABCDABCABDABAA
AAAAAAAAAAAAAAAAAA
END
样例输出
144 35 4.11
44 18 8.0
#include<stdio.h> #include<stdlib.h> #include<string.h> struct Node{ int v; int hash; int a; int parent; }num[200]; int fcmp(const void *a,const void *b) { return ((struct Node *)a)->v-((struct Node *)b)->v; } int fcmp2(const void *a,const void *b) { return ((struct Node *)a)->a-((struct Node *)b)->a; } char c[1000001]; int main(void) { int count,i,d1,d2,ok; while(scanf("%s",c)) { if(strcmp(c,"END")==0) break; d1=strlen(c)*8; count=0; for(i=0;i<200;i++) { num[i].v=0; num[i].hash=0; num[i].parent=-1; num[i].a=i; } for(i=0;c[i];i++) { if(c[i]!='_') { num[c[i]-'A'].v++; } else num[26].v++; } int tmp1,tmp2,flag; count=26; ok=0; while(1) { flag=0; qsort(num,count+1,sizeof(num[0]),fcmp); for(i=0;i<=count;i++) { if(!num[i].hash && num[i].v!=0) { num[i].hash=1; tmp1=i; i++; break; } } while(i<=count) { if(!num[i].hash && num[i].v!=0) { ok=1; num[i].hash=1; tmp2=i; i++; flag=1; break; } i++; } if(!flag) break; num[tmp1].parent=count+1; num[tmp2].parent=count+1; count++; num[count].parent=-1; num[count].v=num[tmp1].v+num[tmp2].v; num[count].a=count; } if(ok==0) { for(i=0;i<=26;i++) { if(num[i].v) d2=num[i].v; } } else { qsort(num,count+1,sizeof(num[0]),fcmp2); num[count].parent=-1; int len,tmp; d2=0; for(i=0;i<=26;i++) { tmp=i; len=0; while(num[tmp].parent!=-1) { tmp=num[tmp].parent; len++; } d2+=len*num[i].v; } } printf("%d %d %.1lf\n",d1,d2,(double)d1/(double)d2); } return 0; } /************************************************************** Problem: 1071 Language: C++ Result: Accepted Time:0 ms Memory:1784 kb ****************************************************************/