题目描述
输入一个字符串,分别用普通ASCII编码(每个字符8bit)和Huffman编码,输出两者编码后的长度,以及压缩比(即编码后两者相除的结果)
样例输入
AAAAABCD
THE_CAT_IN_THE_HAT
END
样例输出
64 13 4.9
144 51 2.8
算法1
(贪心->Huffman树) O ( n l o g n ) O(nlogn) O(nlogn)
本题先统计每个字符的频数,然后按频数的大小排序,之后从小往大贪心地枚举每一个数的频数大小并相加,就可以使得频数大的编码短且频数小的编码长,这样一来就可以是整体字母的编码最短。这其实就是Huffman编码方式。
这里画个图表示下样例一的Huffman树:
另注:这里的Huffman树我是用优先队列来维护,这样提取频数最小值比较方便~~
C++ 代码
#include<iostream>
#include<queue>
#include<string>
#include<algorithm>
#include<cstdio>
using namespace std;
int main()
{
string s;
while(cin >> s && s != "END"){
int cnt = 1,len = 0;
priority_queue<int,vector<int>,greater<int> > heap;
sort(s.begin(),s.end());
int l = s.size();
for(int i = 1;i < l;i ++){
if(s[i] != s[i - 1]){
heap.push(cnt);
cnt = 1;
}
else cnt ++;
}
heap.push(cnt);
if(heap.size() == 1) len += heap.top();
while (heap.size() > 1){
int a = heap.top();heap.pop();
int b = heap.top();heap.pop();
heap.push(a + b);
len += (a + b);
}
heap.pop();
printf("%d %d %.1f\n",l * 8,len,(l * 8.0) / len);
}
return 0;
}