树9 Huffman Codes

问题

In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redundancy Codes", and hence printed his name in the history of computer science. As a professor who gives the final exam problem on Huffman codes, I am encountering a big problem: the Huffman codes are NOT unique. For example, given a string "aaaxuaxz", we can observe that the frequencies of the characters 'a', 'x', 'u' and 'z' are 4, 2, 1 and 1, respectively. We may either encode the symbols as {'a'=0, 'x'=10, 'u'=110, 'z'=111}, or in another way as {'a'=1, 'x'=01, 'u'=001, 'z'=000}, both compress the string into 14 bits. Another set of code can be given as {'a'=0, 'x'=11, 'u'=100, 'z'=101}, but {'a'=0, 'x'=01, 'u'=011, 'z'=001} is NOT correct since "aaaxuaxz" and "aazuaxax" can both be decoded from the code 00001011001001. The students are submitting all kinds of codes, and I need a computer program to help me determine which ones are correct and which ones are not.

Input Specification:

Each input file contains one test case. For each case, the first line gives an integer N (2≤N≤63), then followed by a line that contains all the N distinct characters and their frequencies in the following format:

c[1] f[1] c[2] f[2] ... c[N] f[N]

where c[i] is a character chosen from {'0' - '9', 'a' - 'z', 'A' - 'Z', '_'}, and f[i] is the frequency of c[i] and is an integer no more than 1000. The next line gives a positive integer M (≤1000), then followed by M student submissions. Each student submission consists of N lines, each in the format:

c[i] code[i]

where c[i] is the i-th character and code[i] is an non-empty string of no more than 63 '0's and '1's.

Output Specification:

For each test case, print in each line either "Yes" if the student's submission is correct, or "No" if not.

Note: The optimal solution is not necessarily generated by Huffman algorithm. Any prefix code with code length being optimal is considered correct.

Sample Input:

7
A 1 B 1 C 1 D 3 E 3 F 6 G 6
4
A 00000
B 00001
C 0001
D 001
E 01
F 10
G 11
A 01010
B 01011
C 0100
D 011
E 10
F 11
G 00
A 000
B 001
C 010
D 011
E 100
F 101
G 110
A 00000
B 00001
C 0001
D 001
E 00
F 10
G 11

Sample Output:

Yes
Yes
No
No

解答

 

//
// Created by world on 2023/3/29.
//
#include <iostream>
#include <string>

class Node
{
private:
public:
    int weight;
    Node *left;
    Node *right;

    Node()
    {
        weight = 0;
        left = right = nullptr;
    }

    explicit Node(int w)
    {
        weight = w;
        left = right = nullptr;
    }

    Node(const Node &n)
    {
        weight = n.weight;
        left = n.left;
        right = n.right;
    }

    bool operator>(const Node &n) const
    {
        return weight > n.weight;
    }

    bool operator<=(const Node &n) const
    {
        return weight <= n.weight;
    }

    friend std::ostream &operator<<(std::ostream &out, const Node &n)
    {
        out << n.weight;
        return out;
    }
};

template<typename T>
class MinHeap
{
private:
public:
    size_t size;
    size_t capacity;
    T *elements;

    explicit MinHeap(int maxsize, T minimum) : capacity(maxsize)
    {
        size = 0;
        elements = new T[maxsize + 1];
        elements[0] = minimum;
    }

    MinHeap(T *const &h, size_t n, T minimum) : size(n), capacity(n)
    {
        elements = new T[n + 1];
        elements[0] = minimum;
        for (size_t i = 0; i < n; ++i)
            elements[i + 1] = h[i];
        adjust();
    }

    ~MinHeap()
    {
        delete[]elements;
    }

    bool full() const { return (size == capacity); }

    bool empty() const { return (size == 0); }

    bool insert(T item)
    {
        if (full())
        {
            std::cout << "This MinHeap is full!\n";
            return false;
        }
        size_t i = ++size;
        for (; elements[i >> 1] > item; i >>= 1)
        {
            elements[i] = elements[i >> 1];
        }
        elements[i] = item;
        return true;
    }

    T *remove()
    {
        if (empty())
        {
            std::cout << "This MinHeap is empty!\n";
            return elements;
        }
        T *minimum = new Node(elements[1]);
        T temp = elements[size--];
        size_t parent = 1;
        for (size_t child; parent << 1 <= size; parent = child)
        {
            child = parent << 1;
            if (child != size and elements[child] > elements[child + 1])
                ++child;
            if (temp <= elements[child])
                break;
            else
                elements[parent] = elements[child];
        }
        elements[parent] = temp;
        return minimum;
    }

    void traverse()
    {
        for (size_t i = 1; i <= size; ++i)
            std::cout << elements[i] << ' ';
        std::cout << std::endl;
    }

    void filter(size_t p)
    {
        size_t parent = p;
        T x = elements[p];
        for (size_t child; parent << 1 <= size; parent = child)
        {
            child = parent << 1;
            if (child != size and elements[child] > elements[child + 1])
                ++child;
            if (x <= elements[child])
                break;
            else
                elements[parent] = elements[child];
        }
        elements[parent] = x;
    }

    void adjust()
    {
        for (size_t i = size >> 1; i > 0; --i)
            filter(i);
    }
};

int wpl(Node *n, int height)
{
    if(!n) return 0;
    else
    {
        if ((!n->left) and (!n->right))
            return n->weight * height;
        else
            return (wpl(n->left, height + 1) + wpl(n->right, height + 1));
    }
}

class HTree
{
private:
public:
    Node *t;

    explicit HTree(MinHeap<Node> &m)
    {
        t = nullptr;
        if (m.empty())
            return;
        size_t n = m.size;
        for (int i = 1; i < n; ++i)
        {
            t = new Node;
            t->left = m.remove();
            t->right = m.remove();
            t->weight = t->left->weight + t->right->weight;
            m.insert(*t);
        }
    }

    HTree(int n, Node *a)
    {
        t = new Node;
        Node *q = t;
        char p;
        std::string s;
        for (int j = 0; j < n; ++j)
        {
            std::cin >> p >> s;
            for (int k = 0; k < s.size(); ++k)
            {
                if (s[k] == '0')
                {
                    if (!t->left)
                    {
                        t->left = new Node(a[j].weight);
                    }
                    t = t->left;
                } else
                {
                    if (!t->right)
                    {
                        t->right = new Node(a[j].weight);
                    }
                    t = t->right;
                }
            }
            t = q;
        }
    }

    void traverse(Node *n)
    {
        if (n)
            std::cout << n->weight << ' ';
        else
            return;
        traverse(n->left);
        traverse(n->right);
    }
};

int main()
{
    int N, M;
    std::cin >> N;
    char p;
    Node *a = new Node[N];
    for (int i = 0; i < N; ++i)
        std::cin >> p >> a[i].weight;
    MinHeap<Node> m(a, N, Node(INT32_MIN));
    HTree h(m);
    std::cin >> M;
    int length = wpl(h.t, 0);
    for (int i = 0; i < M; ++i)
    {
        HTree stu(N, a);
//        stu.traverse(stu.t);
        int count = wpl(stu.t, 0);
        if (count == length)
        {
            std::cout << "Yes\n";
        } else
            std::cout << "No\n";
    }
    delete[]a;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值