霍夫曼树

#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);
	}
}