import heapq # модуль для работы с мин. кучей из стандартной библиотеки Python
from collections import Counter # словарь в котором для каждого объекта поддерживается счетчик
from collections import namedtuple
# добавим классы для хранения информации о структуре дерева
# воспользуемся функцией namedtuple из стандартной библиотеки
class Node( namedtuple( "Node" , [ "left" , "right" ] ) ) : # класс для ветвей дерева - внутренних узлов; у них есть потомки
def walk( self , code , acc) :
# чтобы обойти дерево нам нужно:
self .left .walk ( code , acc + "0" ) # пойти в левого потомка, добавив к префиксу "0"
self .right .walk ( code , acc + "1" ) # затем пойти в правого потомка, добавив к префиксу "1"
class Leaf( namedtuple( "Leaf" , [ "char" ] ) ) : # класс для листьев дерева, у него нет потомков, но есть значение символа
def walk( self , code , acc) :
# потомков у листа нет, по этому для значения мы запишем построенный код для данного символа
code [ self .char ] = acc or "0" # если строка длиной 1 то acc = "", для этого случая установим значение acc = "0"
def huffman_encode( s) : # функция кодирования строки в коды Хаффмана
h = [ ] # инициализируем очередь с приоритетами
for ch, freq in Counter( s) .items ( ) : # постоим очередь с помощью цикла, добавив счетчик, уникальный для всех листьев
h.append ( ( freq, len ( h) , Leaf( ch) ) ) # очередь будет представлена частотой символа, счетчиком и самим символом
heapq .heapify ( h) # построим очередь с приоритетами
count = len ( h) # инициализируем значение счетчика длиной очереди
while len ( h) > 1 : # пока в очереди есть хотя бы 2 элемента
freq1, _count1, left = heapq .heappop ( h) # вытащим элемент с минимальной частотой - левый узел
freq2, _count2, right = heapq .heappop ( h) # вытащим следующий элемент с минимальной частотой - правый узел
# поместим в очередь новый элемент, у которого частота равна суме частот вытащенных элементов
heapq .heappush ( h, ( freq1 + freq2, count, Node( left, right) ) ) # добавим новый внутренний узел у которого
# потомки left и right соответственно
count += 1 # инкрементируем значение счетчика при добавлении нового элемента дерева
code = { } # инициализируем словарь кодов символов
if h: # если строка пустая, то очередь будет пустая и обходить нечего
[ ( _freq, _count, root) ] = h # в очереди 1 элемент, приоритет которого не важен, а сам элемент - корень дерева
root.walk ( code , "" ) # обойдем дерева от корня и заполним словарь для получения кодирования Хаффмана
return code # возвращаем словарь символов и соответствующих им кодов
def main( ) :
s = input ( ) # читаем строку длиной до 10**4
code = huffman_encode( s) # кодируем строку
encoded = "" .join ( code [ ch] for ch in s) # отобразим закодированную версию, отобразив каждый символ
# в соответствующий код и конкатенируем результат
print ( len ( code ) , len ( encoded) ) # выведем число символов и длину закодированной строки
for ch in sorted ( code ) : # обойдем символы в словаре в алфавитном порядке с помощью функции sorted()
print ( "{}: {}" .format ( ch, code [ ch] ) ) # выведем символ и соответствующий ему код
print ( encoded) # выведем закодированную строку
if __name__ == "__main__" :
main( impossible)
aW1wb3J0IGhlYXBxICAjINC80L7QtNGD0LvRjCDQtNC70Y8g0YDQsNCx0L7RgtGLINGBINC80LjQvS4g0LrRg9GH0LXQuSDQuNC3INGB0YLQsNC90LTQsNGA0YLQvdC+0Lkg0LHQuNCx0LvQuNC+0YLQtdC60LggUHl0aG9uCmZyb20gY29sbGVjdGlvbnMgaW1wb3J0IENvdW50ZXIgICMg0YHQu9C+0LLQsNGA0Ywg0LIg0LrQvtGC0L7RgNC+0Lwg0LTQu9GPINC60LDQttC00L7Qs9C+INC+0LHRitC10LrRgtCwINC/0L7QtNC00LXRgNC20LjQstCw0LXRgtGB0Y8g0YHRh9C10YLRh9C40LoKZnJvbSBjb2xsZWN0aW9ucyBpbXBvcnQgbmFtZWR0dXBsZQoKIyDQtNC+0LHQsNCy0LjQvCDQutC70LDRgdGB0Ysg0LTQu9GPINGF0YDQsNC90LXQvdC40Y8g0LjQvdGE0L7RgNC80LDRhtC40Lgg0L4g0YHRgtGA0YPQutGC0YPRgNC1INC00LXRgNC10LLQsAojINCy0L7RgdC/0L7Qu9GM0LfRg9C10LzRgdGPINGE0YPQvdC60YbQuNC10LkgbmFtZWR0dXBsZSDQuNC3INGB0YLQsNC90LTQsNGA0YLQvdC+0Lkg0LHQuNCx0LvQuNC+0YLQtdC60LgKY2xhc3MgTm9kZShuYW1lZHR1cGxlKCJOb2RlIiwgWyJsZWZ0IiwgInJpZ2h0Il0pKTogICMg0LrQu9Cw0YHRgSDQtNC70Y8g0LLQtdGC0LLQtdC5INC00LXRgNC10LLQsCAtINCy0L3Rg9GC0YDQtdC90L3QuNGFINGD0LfQu9C+0LI7INGDINC90LjRhSDQtdGB0YLRjCDQv9C+0YLQvtC80LrQuAogICAgZGVmIHdhbGsoc2VsZiwgY29kZSwgYWNjKToKICAgICAgICAjINGH0YLQvtCx0Ysg0L7QsdC+0LnRgtC4INC00LXRgNC10LLQviDQvdCw0Lwg0L3Rg9C20L3QvjoKICAgICAgICBzZWxmLmxlZnQud2Fsayhjb2RlLCBhY2MgKyAiMCIpICAjINC/0L7QudGC0Lgg0LIg0LvQtdCy0L7Qs9C+INC/0L7RgtC+0LzQutCwLCDQtNC+0LHQsNCy0LjQsiDQuiDQv9GA0LXRhNC40LrRgdGDICIwIgogICAgICAgIHNlbGYucmlnaHQud2Fsayhjb2RlLCBhY2MgKyAiMSIpICAjINC30LDRgtC10Lwg0L/QvtC50YLQuCDQsiDQv9GA0LDQstC+0LPQviDQv9C+0YLQvtC80LrQsCwg0LTQvtCx0LDQstC40LIg0Log0L/RgNC10YTQuNC60YHRgyAiMSIKCmNsYXNzIExlYWYobmFtZWR0dXBsZSgiTGVhZiIsIFsiY2hhciJdKSk6ICAjINC60LvQsNGB0YEg0LTQu9GPINC70LjRgdGC0YzQtdCyINC00LXRgNC10LLQsCwg0YMg0L3QtdCz0L4g0L3QtdGCINC/0L7RgtC+0LzQutC+0LIsINC90L4g0LXRgdGC0Ywg0LfQvdCw0YfQtdC90LjQtSDRgdC40LzQstC+0LvQsAogICAgZGVmIHdhbGsoc2VsZiwgY29kZSwgYWNjKToKICAgICAgICAjINC/0L7RgtC+0LzQutC+0LIg0YMg0LvQuNGB0YLQsCDQvdC10YIsINC/0L4g0Y3RgtC+0LzRgyDQtNC70Y8g0LfQvdCw0YfQtdC90LjRjyDQvNGLINC30LDQv9C40YjQtdC8INC/0L7RgdGC0YDQvtC10L3QvdGL0Lkg0LrQvtC0INC00LvRjyDQtNCw0L3QvdC+0LPQviDRgdC40LzQstC+0LvQsAogICAgICAgIGNvZGVbc2VsZi5jaGFyXSA9IGFjYyBvciAiMCIgICMg0LXRgdC70Lgg0YHRgtGA0L7QutCwINC00LvQuNC90L7QuSAxINGC0L4gYWNjID0gIiIsINC00LvRjyDRjdGC0L7Qs9C+INGB0LvRg9GH0LDRjyDRg9GB0YLQsNC90L7QstC40Lwg0LfQvdCw0YfQtdC90LjQtSBhY2MgPSAiMCIKCmRlZiBodWZmbWFuX2VuY29kZShzKTogICMg0YTRg9C90LrRhtC40Y8g0LrQvtC00LjRgNC+0LLQsNC90LjRjyDRgdGC0YDQvtC60Lgg0LIg0LrQvtC00Ysg0KXQsNGE0YTQvNCw0L3QsAogICAgaCA9IFtdICAjINC40L3QuNGG0LjQsNC70LjQt9C40YDRg9C10Lwg0L7Rh9C10YDQtdC00Ywg0YEg0L/RgNC40L7RgNC40YLQtdGC0LDQvNC4CiAgICBmb3IgY2gsIGZyZXEgaW4gQ291bnRlcihzKS5pdGVtcygpOiAjINC/0L7RgdGC0L7QuNC8INC+0YfQtdGA0LXQtNGMINGBINC/0L7QvNC+0YnRjNGOINGG0LjQutC70LAsINC00L7QsdCw0LLQuNCyINGB0YfQtdGC0YfQuNC6LCDRg9C90LjQutCw0LvRjNC90YvQuSDQtNC70Y8g0LLRgdC10YUg0LvQuNGB0YLRjNC10LIKICAgICAgICBoLmFwcGVuZCgoZnJlcSwgbGVuKGgpLCBMZWFmKGNoKSkpICAjINC+0YfQtdGA0LXQtNGMINCx0YPQtNC10YIg0L/RgNC10LTRgdGC0LDQstC70LXQvdCwINGH0LDRgdGC0L7RgtC+0Lkg0YHQuNC80LLQvtC70LAsINGB0YfQtdGC0YfQuNC60L7QvCDQuCDRgdCw0LzQuNC8INGB0LjQvNCy0L7Qu9C+0LwKICAgIGhlYXBxLmhlYXBpZnkoaCkgICMg0L/QvtGB0YLRgNC+0LjQvCDQvtGH0LXRgNC10LTRjCDRgSDQv9GA0LjQvtGA0LjRgtC10YLQsNC80LgKICAgIGNvdW50ID0gbGVuKGgpICMg0LjQvdC40YbQuNCw0LvQuNC30LjRgNGD0LXQvCDQt9C90LDRh9C10L3QuNC1INGB0YfQtdGC0YfQuNC60LAg0LTQu9C40L3QvtC5INC+0YfQtdGA0LXQtNC4CiAgICB3aGlsZSBsZW4oaCkgPiAxOiAgIyDQv9C+0LrQsCDQsiDQvtGH0LXRgNC10LTQuCDQtdGB0YLRjCDRhdC+0YLRjyDQsdGLIDIg0Y3Qu9C10LzQtdC90YLQsAogICAgICAgIGZyZXExLCBfY291bnQxLCBsZWZ0ID0gaGVhcHEuaGVhcHBvcChoKSAgIyDQstGL0YLQsNGJ0LjQvCDRjdC70LXQvNC10L3RgiDRgSDQvNC40L3QuNC80LDQu9GM0L3QvtC5INGH0LDRgdGC0L7RgtC+0LkgLSDQu9C10LLRi9C5INGD0LfQtdC7CiAgICAgICAgZnJlcTIsIF9jb3VudDIsIHJpZ2h0ID0gaGVhcHEuaGVhcHBvcChoKSAgIyDQstGL0YLQsNGJ0LjQvCDRgdC70LXQtNGD0Y7RidC40Lkg0Y3Qu9C10LzQtdC90YIg0YEg0LzQuNC90LjQvNCw0LvRjNC90L7QuSDRh9Cw0YHRgtC+0YLQvtC5IC0g0L/RgNCw0LLRi9C5INGD0LfQtdC7CiAgICAgICAgIyDQv9C+0LzQtdGB0YLQuNC8INCyINC+0YfQtdGA0LXQtNGMINC90L7QstGL0Lkg0Y3Qu9C10LzQtdC90YIsINGDINC60L7RgtC+0YDQvtCz0L4g0YfQsNGB0YLQvtGC0LAg0YDQsNCy0L3QsCDRgdGD0LzQtSDRh9Cw0YHRgtC+0YIg0LLRi9GC0LDRidC10L3QvdGL0YUg0Y3Qu9C10LzQtdC90YLQvtCyCiAgICAgICAgaGVhcHEuaGVhcHB1c2goaCwgKGZyZXExICsgZnJlcTIsIGNvdW50LCBOb2RlKGxlZnQsIHJpZ2h0KSkpICMg0LTQvtCx0LDQstC40Lwg0L3QvtCy0YvQuSDQstC90YPRgtGA0LXQvdC90LjQuSDRg9C30LXQuyDRgyDQutC+0YLQvtGA0L7Qs9C+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMg0L/QvtGC0L7QvNC60LggbGVmdCDQuCByaWdodCDRgdC+0L7RgtCy0LXRgtGB0YLQstC10L3QvdC+CiAgICAgICAgY291bnQgKz0gMSAgIyDQuNC90LrRgNC10LzQtdC90YLQuNGA0YPQtdC8INC30L3QsNGH0LXQvdC40LUg0YHRh9C10YLRh9C40LrQsCDQv9GA0Lgg0LTQvtCx0LDQstC70LXQvdC40Lgg0L3QvtCy0L7Qs9C+INGN0LvQtdC80LXQvdGC0LAg0LTQtdGA0LXQstCwCiAgICBjb2RlID0ge30gICMg0LjQvdC40YbQuNCw0LvQuNC30LjRgNGD0LXQvCDRgdC70L7QstCw0YDRjCDQutC+0LTQvtCyINGB0LjQvNCy0L7Qu9C+0LIKICAgIGlmIGg6ICAjINC10YHQu9C4INGB0YLRgNC+0LrQsCDQv9GD0YHRgtCw0Y8sINGC0L4g0L7Rh9C10YDQtdC00Ywg0LHRg9C00LXRgiDQv9GD0YHRgtCw0Y8g0Lgg0L7QsdGF0L7QtNC40YLRjCDQvdC10YfQtdCz0L4KICAgICAgICBbKF9mcmVxLCBfY291bnQsIHJvb3QpXSA9IGggICMg0LIg0L7Rh9C10YDQtdC00LggMSDRjdC70LXQvNC10L3Rgiwg0L/RgNC40L7RgNC40YLQtdGCINC60L7RgtC+0YDQvtCz0L4g0L3QtSDQstCw0LbQtdC9LCDQsCDRgdCw0Lwg0Y3Qu9C10LzQtdC90YIgLSDQutC+0YDQtdC90Ywg0LTQtdGA0LXQstCwCiAgICAgICAgcm9vdC53YWxrKGNvZGUsICIiKSAgIyDQvtCx0L7QudC00LXQvCDQtNC10YDQtdCy0LAg0L7RgiDQutC+0YDQvdGPINC4INC30LDQv9C+0LvQvdC40Lwg0YHQu9C+0LLQsNGA0Ywg0LTQu9GPINC/0L7Qu9GD0YfQtdC90LjRjyDQutC+0LTQuNGA0L7QstCw0L3QuNGPINCl0LDRhNGE0LzQsNC90LAKICAgIHJldHVybiBjb2RlICAjINCy0L7Qt9Cy0YDQsNGJ0LDQtdC8INGB0LvQvtCy0LDRgNGMINGB0LjQvNCy0L7Qu9C+0LIg0Lgg0YHQvtC+0YLQstC10YLRgdGC0LLRg9GO0YnQuNGFINC40Lwg0LrQvtC00L7QsgoKZGVmIG1haW4oKToKICAgIHMgPSBpbnB1dCgpICAjINGH0LjRgtCw0LXQvCDRgdGC0YDQvtC60YMg0LTQu9C40L3QvtC5ICDQtNC+IDEwKio0CiAgICBjb2RlID0gaHVmZm1hbl9lbmNvZGUocykgICMg0LrQvtC00LjRgNGD0LXQvCDRgdGC0YDQvtC60YMKICAgIGVuY29kZWQgPSAiIi5qb2luKGNvZGVbY2hdIGZvciBjaCBpbiBzKSAgIyDQvtGC0L7QsdGA0LDQt9C40Lwg0LfQsNC60L7QtNC40YDQvtCy0LDQvdC90YPRjiDQstC10YDRgdC40Y4sINC+0YLQvtCx0YDQsNC30LjQsiDQutCw0LbQtNGL0Lkg0YHQuNC80LLQvtC7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMg0LIg0YHQvtC+0YLQstC10YLRgdGC0LLRg9GO0YnQuNC5INC60L7QtCDQuCDQutC+0L3QutCw0YLQtdC90LjRgNGD0LXQvCDRgNC10LfRg9C70YzRgtCw0YIKICAgIHByaW50KGxlbihjb2RlKSwgbGVuKGVuY29kZWQpKSAgIyDQstGL0LLQtdC00LXQvCDRh9C40YHQu9C+INGB0LjQvNCy0L7Qu9C+0LIg0Lgg0LTQu9C40L3RgyDQt9Cw0LrQvtC00LjRgNC+0LLQsNC90L3QvtC5INGB0YLRgNC+0LrQuAogICAgZm9yIGNoIGluIHNvcnRlZChjb2RlKTogIyDQvtCx0L7QudC00LXQvCDRgdC40LzQstC+0LvRiyDQsiDRgdC70L7QstCw0YDQtSDQsiDQsNC70YTQsNCy0LjRgtC90L7QvCDQv9C+0YDRj9C00LrQtSDRgSDQv9C+0LzQvtGJ0YzRjiDRhNGD0L3QutGG0LjQuCBzb3J0ZWQoKQogICAgICAgIHByaW50KCJ7fToge30iLmZvcm1hdChjaCwgY29kZVtjaF0pKSAgIyDQstGL0LLQtdC00LXQvCDRgdC40LzQstC+0Lsg0Lgg0YHQvtC+0YLQstC10YLRgdGC0LLRg9GO0YnQuNC5INC10LzRgyDQutC+0LQKICAgIHByaW50KGVuY29kZWQpICAjINCy0YvQstC10LTQtdC8INC30LDQutC+0LTQuNGA0L7QstCw0L3QvdGD0Y4g0YHRgtGA0L7QutGDCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgbWFpbihpbXBvc3NpYmxlKQ==