POJ1521---Entropy

POJ—Entropy

题目描述 英文

熵编码器是一种数据编码方法,其通过对去除了“浪费”或“额外”信息的消息进行编码来实现无损数据压缩。
考虑文本“AAAAABCD”。使用ASCII,编码需要64位。由于字形“A”以更高的频率出现,可以通过用更少的位编码来做得更好吗?最佳编码是将“A”编码为“0”,将“B”编码为“10”,将“C”编码为“110”,和“D”与“111”。(这显然不是唯一的最佳编码,因为很明显,对于任何给定的编码,B,C和D的编码可以自由地互换,而不会增加最终编码消息的大小。)使用此编码,消息编码为只有13位到“0000010110111”,压缩比为4.9:1(也就是说,最终编码消息中的每个位表示与原始编码中4.9位一样多的信息)。

输入

输入文件将包含一个文本字符串列表,每行一个。文本字符串将仅包含大写字母数字字符和下划线(用于代替空格)。输入的结尾将由仅包含单词“END”作为文本字符串的行发出信号。

输出

对于输入中的每个文本字符串,输出8位ASCII编码的位长度,最佳无前缀可变长度编码的位长度,以及精确到一个小数点的压缩率。

样例输入

AAAAABCD

THE_CAT_IN_THE_HAT

END

样例输出

64 13 4.9

144 51 2.8

解题思路

本题考察的主要内容为哈夫曼树
案例第一个输出表示字符串用ASCII存储所使用的位数,即 长度 * 8即可.第二个输出为使用二进制编码来存储字符,但要求位数最少,这时我们得使用哈夫曼编码了.我们在处理时只需要求出所给字符的哈夫曼编码的WPL即为最短字符编码.
第三个输出即为第一,第二的商.

代码
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<queue>
#include<vector>

using namespace std;
int arr[50],total;
string str;
priority_queue<int,vector<int>,greater<int> > Q;
int main()
{
	while(cin>>str&&str!="END"){
		while(!Q.empty()){
			Q.pop();
		}
		memset(arr,0,sizeof(arr));
		total = 0;
		for(int i = 0; i < str.size(); i++){
			if(str[i]!='_'){
				arr[str[i]-'A']++;
			}else{
				arr[26]++;
			}
		}
		//cout<<"------------------"<<endl;
		for(int i = 0; i <=26; i++){
			
			if(arr[i]){
				Q.push(arr[i]);
				//cout<<arr[i]<<"\t";				
			}
		}
		//cout<<endl;
		//cout<<"-----------------"<<endl;
		while(Q.size() > 1){
			int w1 = Q.top();
			Q.pop();
			int w2 = Q.top();
			Q.pop();
			Q.push(w1+w2);
			total+=w1+w2;
		}
		printf("%d %d %.1lf\n",str.size()*8,total,str.size()*8.0/total);		
	}
	return 0;
}
代码解析

在进行计算哈夫曼树的WPL时,要注意如果只有一个字符,那么长度就是1.当大于1个字符,则进行构建哈夫曼树.

心得收获
  1. 当遇到字符时我们将其映射为数字的处理方式: 如A==> arr[0]=arr[ str[i] – ‘A’ ] (当str[i]
    == A), B==> arr[1]=arr[ str[i] – ‘B’ ] (当str[i] == B).
  2. 在竞赛时对于输入输出最好用C语言的,效率更高.
  3. 优先队列的使用.
  4. 特殊情况的处理,如方法一需要考虑字符种类个数是否大于1,方法二则可不用考虑.
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱编程的大李子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值