霍夫曼树
#include<cstdio>
#include<string.h>
#include<iostream>
#include<string>
using namespace std;
#define LEFT(i) 2*i
#define RIGHT(i) 2*i+1
#define PARENT(i) i/2
int heapsize,root;
int finalcode[200];
struct Word{
int num,number;
double freq;
}word[200];
struct Node{
int num,l,r;
bool leaf;
}node[200];
void exchange(int s,int t){
int tem1;
double tem2;
int tem3;
tem1=word[s].num;
tem2=word[s].freq;
tem3=word[s].number;
word[s].num=word[t].num;
word[s].freq=word[t].freq;
word[s].number=word[t].number;
word[t].num=tem1;
word[t].freq=tem2;
word[t].number=tem3;
}
void min_heap(int i){
int l,r,largest;
l=LEFT(i);
r=RIGHT(i);
if(l>heapsize && r>heapsize)
return;
if(l<=heapsize && word[l].freq<word[i].freq)
largest=l;
else
largest=i;
if(r<=heapsize && word[r].freq<word[largest].freq)
largest=r;
if(largest!=i){
exchange(i,largest);
min_heap(largest);
}
}
void init_heap(){
int i;
for(i=heapsize/2;i;i--){
min_heap(i);
}
}
void insert(){
exchange(1,heapsize);
min_heap(1);
}
void clear(){
exchange(1,heapsize);
heapsize--;
min_heap(1);
}
void addedge(int parent,int l,int r,int lmark,int rmark){
node[parent].leaf=0;
node[parent].l=lmark;
node[parent].r=rmark;
if(l!=-1){
node[lmark].leaf=1;
node[lmark].num=l;
}
if(r!=-1){
node[rmark].leaf=1;
node[rmark].num=r;
}
}
void code(int now,int i){
int j;
if(node[now].leaf){
finalcode[node[now].num]=i;
return;
}
code(node[now].l,i+1);
code(node[now].r,i+1);
}
int main(){
char temp;
int i,times[200];
int totalwords,nodes;
string str;
while(cin>>str && !(str=="END")){
memset(times,0,sizeof(times));
totalwords=0;
for(i=0;i<str.size();i++){
temp=str[i];
times[temp]++;
totalwords++;
}
heapsize=0;
for(i=0;i<=130;i++){
if(times[i]){
word[++heapsize].number=-1;
word[heapsize].num=i;
word[heapsize].freq=(double)times[i]/totalwords;
}
}
nodes=0;
init_heap();
while(heapsize>1){
int l,r,lmark,rmark;
double fl,fr;
l=word[1].num;
fl=word[1].freq;
if(word[1].number==-1){
++nodes;
lmark=nodes;
}
else
lmark=word[1].number;
clear();
r=word[1].num;
fr=word[1].freq;
if(word[1].number==-1){
++nodes;
rmark=nodes;
}
else
rmark=word[1].number;
clear();
word[++heapsize].freq=fl+fr;
word[heapsize].num=-1;
word[heapsize].number=++nodes;
insert();
addedge(nodes,l,r,lmark,rmark);
}
root=nodes;
if(nodes)
code(root,0);
else
finalcode[word[1].num]=1;
int total1=0,total2=0;
for(i=0;i<=130;i++){
if(times[i]){
total1+=times[i]*8;
total2+=times[i]*finalcode[i];
}
}
printf("%d %d %.1f\n",total1,total2,(double)total1/total2);
}
}