Problem Description
文本编码是计算机通信中的常见问题。
以文本“AAAAABCD”为例,如果使用ASCII,则一共需要64位(因为每个字符的ASCII编码都是需要8位)。
对应的,如果我们将A编码为“00”,“B”为“01”,“C”为“10”,“D”为“11”,那么我们可以只编码16位; 得到的位模式将是“0000000000011011”。然而,这仍然是一种固定长度的编码。
由于字符“A”的出现频率较高,我们是否可以通过用较少的位对它进行编码来获得更好的效果?
事实上,我们确实可以。
最佳编码是将“A”标记为“0”,“B”标记为“10”,“C”标记为“110”,“D”标记为“111”。(显然,这不是唯一的最佳编码,因为很显然,对B,C和D可以自由交换,而不增加最终编码的大小。)
使用这种编码,上述的字符串仅需要13位,编码为“0000010110111”,相对ASCII编码方案,压缩比为4.9比1。通过从左到右读取该编码,您会发现,无前缀编码可以很容易地将其解码为原始文本,即使代码具有不同的位长度。
Input
输入包含多组文本字符串,每行一个。
文本字符串将只包含大写字母、数字字符和下划线(用于代替空格)。
单词“END”表示输入结束,不做处理。
Output
对于输入中的每个文本字符串,输出8位ASCII编码的长度、最佳编码的长度,以及对应的压缩率比值,压缩比精确到小数点后一位。
输入样例
AAAAABCD
THE_CAT_IN_THE_HAT
END
输出样例
64 13 4.9
144 51 2.8
附ac代码
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<cmath> using namespace std; int ch[40]; int bfs() { int a,b; int ans=0; priority_queue<int,vector<int>,greater<int> >qu;//实现小顶堆 优先队列默认大顶堆 //注意int的尖括号和queue的尖括号之间要有空格 for(int i=0;i<=37;++i) { if(ch[i]) qu.push(ch[i]); //哈夫曼编码的编码长度与树的深度相同故求总长即求树的带权路径 } if(qu.size()==1) ans=qu.top(); //哈夫曼编码若结点大于1一定时完全二叉树 while(qu.size()>1) { a=qu.top(); qu.pop(); b=qu.top(); qu.pop(); ans+=(a+b); qu.push(a+b); } return ans; } int main() { string str; while(cin>>str) { if(str[0]=='E'&&str[1]=='N'&&str[2]=='D'&&str.size()==3) break; memset(ch,0,sizeof(ch)); for(int i=0;i<str.size();++i) { if(str[i]=='_') ch[26]++; else { if(str[i]>='A'&&str[i]<='Z') ch[str[i]-'A']++; else ch[str[i]-'0'+28]++; } } int ans1=str.size()*8,ans2=bfs(); double ans3=round(((double)ans1/ans2)*10)/10; printf("%d %d %.1lf\n",ans1,ans2,ans3); } return 0; }
标签:编码,hdu,文本,qu,哈夫曼,int,str,include
From: https://www.cnblogs.com/ruoye123456/p/16943156.html