#include <iostream>

struct Node{
    char letter;
    int freq;
    Node* left = nullptr;
    Node* right = nullptr;
};

struct MinHeap{
    int size;
    int capacity;
    Node** arr;
};

void SiftDown(MinHeap* minHeap, int i) {
    int j = i;
    int left = 2 * i + 1;
    int right = 2 * i + 2;
    if (left < minHeap->size && minHeap->arr[left]->freq < minHeap->arr[j]->freq) {
        j = left;
    }
    if (right < minHeap->size && minHeap->arr[right]->freq < minHeap->arr[j]->freq) {
        j = right;
    }
    if (j != i) {
        Node* temp = minHeap->arr[j];
        *minHeap->arr[j] = *minHeap->arr[i];
        *minHeap->arr[i] = *temp;
        SiftDown(minHeap, j);
    }
}

void SiftUp(MinHeap* minHeap) {
    int n = minHeap->size - 1;
    int i;
    for (i = n / 2 - 1; i >= 0; --i) {
        SiftDown(minHeap, i);
    }
}

MinHeap* HaffmanBuild(int freq[], char letters[], int size) {
    MinHeap* minHeap = new MinHeap();
    minHeap->size = 0;
    minHeap->capacity = size;
    for (int i = 0; i < size; ++i) {
        minHeap->arr[i] = new Node();
        minHeap->arr[i]->freq = freq[i];
        minHeap->arr[i]->letter = letters[i];
    }
    minHeap->size = size;
    SiftUp(minHeap);
    return minHeap;
}

Node* ExtractMin(MinHeap* minHeap) {
    Node* temp = minHeap->arr[0];
    minHeap->arr[0] = minHeap->arr[minHeap->size - 1];
    --minHeap->size;
    SiftDown(minHeap, 0);
    return temp;
}

void Insert(MinHeap* minHeap, Node* temp) {
    ++minHeap->size;
    int i = minHeap->size - 1;
    while (i && temp->freq < minHeap->arr[(i - 1) / 2]->freq) {
        minHeap->arr[i] = minHeap->arr[(i - 1) / 2];
        i = (i - 1) / 2;
    }
    minHeap->arr[i] = temp;
}

Node* Build(int freq[], char letters[], int size) {
    MinHeap* minHeap = HaffmanBuild(freq, letters, size);
    while (minHeap->size != 1) {
        Node* left = ExtractMin(minHeap);
        Node* right = ExtractMin(minHeap);
        Node* parent = new Node();
        parent->freq = left->freq + right->freq;
        parent->left = left;
        parent->right = right;
        Insert(minHeap, parent);
    }
    return ExtractMin(minHeap);
}

void printArr(std::string str, int n)
{
    int i;
    for (i = 0; i < n; ++i)
        std::cout << str;

    std::cout << "\n";
}

void printCodes(struct Node* root, std::string str,
                int top)

{

    // Assign 0 to left edge and recur
    if (root->left) {
        printCodes(root->left, str + "0", top + 1);
    }

    // Assign 1 to right edge and recur
    if (root->right) {

        printCodes(root->right, str + "1", top + 1);
    }

    // If this is a leaf node, then
    // it contains one of the input
    // characters, print the character
    // and its code from arr[]
    if (!(root->left) && !(root->right)) {

        std::cout << root->letter << ": ";
        printArr(str, top);
    }
}

int main() {
    std::string s;
    std::cin >> s;
    int frequency[26] = {0};
    char letters[26] = {""};
    for (int i = 0; i < s.length(); ++i) {
        frequency[s[i] - 'a'] += 1;
        letters[s[i] - 'a'] = s[i];
    }
    /*for (int i = 0; i < 26; ++i) {
        std::cout << frequency[i] << " " << letters[i] << '\n';
    }*/
    int size = sizeof(letters) / sizeof(letters[0]);
    Node* root = Build(frequency, letters, size);
    printCodes(root, "", 0);

    return 0;
}
 why when input is daccaba it returns Process finished with exit code 139 (interrupted by signal 11: SIGSEGV) instead of the codes of each letter