问题
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;
}