#include <iostream>
#include <stack>
#include <queue>
using namespace std;
struct Node {
char name=' ';
int code[200];
int num = 0;//code的下标
int weight = 0;//权重(次数)
Node* lchild;//左孩子
Node* rchild;//右孩子
Node* parent;
Node* rparent;
Node* lparent;
Node() {}
Node(char c, Node* lc = nullptr, Node* t = nullptr) {
name = c;
lchild = rchild = t;
parent = rparent = lparent = t;
}
Node(int n, Node* lc = nullptr, Node* t = nullptr) {
weight = n;
lchild = rchild = t;
parent = rparent = lparent = t;
}
};
void sort(Node** arr, int n) {//排序
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j]->weight <= arr[j + 1]->weight) {
Node* t = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = t;
}
}
}
}
Node* solve(Node** arr, int len) {
Node* parent = nullptr;
while (len != 0) {
sort(arr, len);
Node* first = arr[len-1];
Node* second = arr[len-2];
len -= 2;
parent = new Node(first->weight + second->weight);
parent->lchild = first;
parent->rchild = second;
first->parent = second->parent = parent;
first->rparent = second->lparent = parent;
if (len == 0)
return parent;
arr[len] = parent;
len++;
}
return nullptr;
}
void seekCode(Node* tree, char c) {
queue<Node*> q;
q.push(tree);
while (!q.empty()) {
Node* t = q.front();
q.pop();
if (t->name == c) {//找到
Node* t1 = t;
Node* t2 = t1->parent;
while (t2 != nullptr) {
//判断父子关系
if (t2->lchild == t1 && t1->rparent == t2 ) t->code[t->num] = 0;
else t->code[t->num] = 1;
t->num++;
t1 = t2;
t2 = t1->parent;
}
break;
}
if(t->lchild != nullptr)
q.push(t->lchild);
if(t->rchild != nullptr)
q.push(t->rchild);
}
}
int main() {
int n;
int len = 0;//代表元素的个数
cin >> n;
char c;
Node** arr = new Node*[10000];
Node** temp = new Node*[10000];
//-------------得到每个字母出现的次数
for (int i = 0; i < n; i++) {
cin >> c;
int flag = 0;
for (int j = 0; j < len; j++) {
if (arr[j]->name == c) {
flag = 1;
arr[j]->weight++;
break;
}
}
if (!flag) {
arr[len] = new Node(c);
arr[len]->weight++;
len++;
}
}
//---------------备用
sort(arr, len);
for (int i = 0; i < len; i++)
temp[i] = arr[i];
//----------------构建哈夫曼树
Node* tree = solve(arr, len);
for (int i = 0; i < len; i++)
seekCode(tree, temp[i]->name);
for (int i = 0; i < len; i++) {
cout << temp[i]->name << " " << temp[i]->weight << " ";
for (int j = temp[i]->num-1 ; j >= 0; j--)
cout << temp[i]->code[j];
cout << endl;
}
}