Problem:
Huffman Coding

We want to encode a given string $S$ to a binary string. Each alphabet character in $S$ should be mapped to a different variable-length code and the code must not be a prefix of others.

Huffman coding is known as one of ways to obtain a code table for such encoding.

For example, we consider that appearance frequencycies of each alphabet character in $S$ are as follows:

a

b

c

d

e

f

freq.

45

13

12

16

9

5

code

0

101

100

111

1101

1100

We can obtain "Huffman codes" (the third row of the table) using Huffman's algorithm.

The algorithm finds a full binary tree called "Huffman tree" as shown in the following figure.

To obtain a Huffman tree, for each alphabet character, we first prepare a node which has no parents and a frequency (weight) of the alphabet character. Then, we repeat the following steps:

Choose two nodes, $x$ and $y$, which has no parents and the smallest weights.

Create a new node $z$ whose weight is the sum of $x$'s and $y$'s.

Add edge linking $z$ to $x$ with label $0$ and to $y$ with label $1$. Then $z$ become their parent.

If there is only one node without a parent, which is the root, finish the algorithm. Otherwise, go to step 1.

Finally, we can find a "Huffman code" in a path from the root to leaves.

Task

Given a string $S$, output the length of a binary string obtained by using Huffman coding for $S$.

Input

$S$

A string $S$ is given in a line.

Output

Print the length of a binary string in a line.

Constraints

$1 \le |S| \le 10^5$

$S$ consists of lowercase English letters.

Sample Input 1

abca

Sample Output 1

6

Sample Input 2

aaabbcccdeeeffg

Sample Output 2

41

Sample Input 3

z

Sample Output 3

1

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using static System.Math;
using System.Text.RegularExpressions;

namespace CsharpSpiral {
    partial class Program {
        static void Main(string[] args) {
            var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = true };
            Console.SetOut(sw);
            new Program().Solve(new ConsoleInput(Console.In, ' '));
            Console.Out.Flush();
        }
        public void Solve(ConsoleInput cin) {
            var Counter = new int[26];
            var str = cin.Read;
            foreach(char c in str) {
                Counter[c - 'a']++;
            }
            var G = new HuffmanNode[26];
            for(int i = 0; i < 26; i++) {
                G[i] = new HuffmanNode((char)(i + 'a'), Counter[i]);
            }
            var Orphan = new PriorityQueue<HuffmanNode>(false);
            Orphan.Push(G.Where(n => n.prob > 0));
            if(Orphan.length == 1) {
                Console.WriteLine(str.Length);
                return;
            }
            while(Orphan.length > 1) {
                var x = Orphan.Pop();
                var y = Orphan.Pop();
                var z = new HuffmanNode(x,y);
                Orphan.Push(z);
            }
            var Root = Orphan.Pop();
            var codes = new string[26];
            for(int i = 0; i < 26; i++) {
                codes[i] = "";
                var cursor = G[i];
                if(cursor.prob == 0) continue;
                while(cursor != Root) {
                    codes[i] += cursor.isLeftChild ? "0" : "1";
                    cursor = cursor.Parent;
                }
                codes[i] = new string(codes[i].Reverse().ToArray());
            }
            var lens = codes.Select(c => c.Length).ToArray();
            var res = str.Sum(c => lens[c - 'a']);
            Console.WriteLine(res);
        }
        class HuffmanNode:IComparable<HuffmanNode> {
            public char value { get; set; }
            public int prob { get; set; }
            public HuffmanNode Left { get; set; }
            public HuffmanNode Right { get; set; }
            public HuffmanNode Parent{ get; set; }
            public bool isLeftChild { get; set; }
            public HuffmanNode(char mValue, int mProb) {
                value = mValue;prob = mProb;
            }
            public HuffmanNode(HuffmanNode x, HuffmanNode y) {
                prob = x.prob + y.prob;
                Left = x; Right = y;
                x.Parent = this; y.Parent = this;
                x.isLeftChild = true; y.isLeftChild = false;
            }
            public int CompareTo(HuffmanNode n) => prob.CompareTo(n.prob);

        }
    }

    static class ExtendClass {
        public static void Swap<T>(this T[] X, int i, int j) {
            T tmp = X[i];
            X[i] = X[j];
            X[j] = tmp;
        }
        public static string Join<T>(this T[] X, string separator = " ") => string.Join(separator, X);
        public static S[] Clone<S>(this S[] src) where S : struct {
            var res = new S[src.Length];
            Array.Copy(src, res, src.Length);
            return res;
        }
    }
    class PriorityQueue<T> where T : IComparable<T> {
        private readonly List<T> body = new List<T>();
        private Comparer<T> comparer { get; set; }
        public PriorityQueue(bool maxTop = true) {
            comparer
            = maxTop ? Comparer<T>.Create((T i, T j) => i.CompareTo(j))
            : Comparer<T>.Create((T i, T j) => j.CompareTo(i));
        }
        public PriorityQueue(Comparer<T> mComparer) { comparer = mComparer; }
        //suppose Me>Her if isRootMaximum
        int Compare(T Me, T Her) => comparer.Compare(Me, Her);
        int Compare(int x, int y) => Compare(body[x], body[y]);
        void Swap(int x, int y) { T tmp = body[x]; body[x] = body[y]; body[y] = tmp; }
        public void Push(T elem) {
            body.Add(elem);
            //the parent of n-th element is the ((n+1)>>1)-1-th
            int j = lastIndex;
            while(j > 0) {
                int parent = ((j + 1) >> 1) - 1;
                if(Compare(parent, j) < 0)
                    Swap(parent, j);
                else break;
                j = parent;
            }
        }
        public void Push(IEnumerable<T> seq) {
            foreach(var item in seq) {
                Push(item);
            }
        }
        public T Pop() {
            T top = body[0];
            Swap(0, lastIndex);
            body.RemoveAt(lastIndex);
            var newComer = 0;
            while(newComer < length) {
                var leftChild = ((newComer + 1) << 1) - 1;
                if(leftChild >= length) break;
                var toSwap = leftChild;
                var rightChild = leftChild + 1;
                if(rightChild < length && Compare(leftChild, rightChild) < 0)
                    toSwap = rightChild;
                if(Compare(newComer, toSwap) < 0)
                    Swap(toSwap, newComer);
                else break;
                newComer = toSwap;
            }
            return top;
        }
        public T Top { get { return body[0]; } }
        public int length { get { return body.Count(); } }
        private int lastIndex { get { return body.Count() - 1; } }
        public bool Any() => body.Any();
        public string Emit() { return body.ToArray().Join(","); }
    }

    class ConsoleInput {
        private readonly TextReader _stream;
        private readonly char _separator = ' ';
        private readonly Queue<string> inputStream;
        public ConsoleInput(TextReader stream, char separator = ' ') {
            this._separator = separator;
            this._stream = stream;
            inputStream = new Queue<string>();
        }
        public string Read {
            get {
                if(inputStream.Count != 0) return inputStream.Dequeue();
                string[] tmp = _stream.ReadLine().Split(_separator);
                for(int i = 0; i < tmp.Length; ++i)
                    inputStream.Enqueue(tmp[i]);
                return inputStream.Dequeue();
            }
        }
        public string ReadLine { get { return _stream.ReadLine(); } }
        public int ReadInt { get { return int.Parse(Read); } }
        public long ReadLong { get { return long.Parse(Read); } }
        public double ReadDouble { get { return double.Parse(Read); } }
        public string[] ReadStrArray(long N) {
            var ret = new string[N];
            for(long i = 0; i < N; ++i)
                ret[i] = Read;
            return ret;
        }
        public int[] ReadIntArray(long N) { var ret = new int[N]; for(long i = 0; i < N; ++i) ret[i] = ReadInt; return ret; }
        public long[] ReadLongArray(long N) { var ret = new long[N]; for(long i = 0; i < N; ++i) ret[i] = ReadLong; return ret; }
        public double[] ReadDoubleArray(long N) { var ret = new double[N]; for(long i = 0; i < N; ++i) ret[i] = ReadDouble; return ret; }
    }
}