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 Ndistinct 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', '_'}, andf[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
注意:
哈夫曼树要求树没有度为1的结点,这里题目要求编码可以有度为1的结点,只要编码最优即可。
结构设计:
根据输入,自己构建一棵哈夫曼树,有N个元素,所以所有结点数量是2N-1,把每个结点都存在数组里,前N个结点就是叶子结点,后N-1个存合并出来的结点。
判断正确依据:
- WPL值相同
- 前缀码不相同
求WPL:
- 从叶子结点开始依次访问父结点即可。
- 学生编码的WPL很简单,直接编码长度*权值。
前缀码:
- 字符串匹配,如果匹配到位置为0,就说明有前缀相同。
#include
#include
#include
using namespace std;
class HuffmanTree {
struct Node {
Node(int w = 0) :weight(w), left(NULL), right(NULL), parent(NULL) {}
int weight;
Node* left;
Node* right;
Node* parent;
};
class MinHeap {
public:
MinHeap(int N) {
cbtree = new Node*[N + 1];
//set samllest guard
cbtree[0] = new Node(-1);
size = 0;
};
~MinHeap() {
delete cbtree[0];
cbtree[0] = NULL;
delete[] cbtree;
}
int Size() {
return size;
}
void Insert(Node* item) {
int i = ++size;
for (; item->weight < cbtree[i / 2]->weight; i = i / 2) {
cbtree[i] = cbtree[i / 2];
}
cbtree[i] = item;
return;
}
Node* DeleteMin() {
Node* min_node = cbtree[1]; // the minimun item
Node* last_node = cbtree[size]; // the last item
cbtree[size--] = NULL; //clear the last pointer
int child, parant = 1;
// loop until parant has no children
while (parant * 2 <= size) {
child = 2 * parant;
// has right child && get the minimun of them
if (child != size && cbtree[child + 1]->weight < cbtree[child]->weight) {
child++;
}
if (last_node->weight < cbtree[child]->weight) {
// item is less than its child, Ok
break;
} else {
// child is less then parent, move to parent
cbtree[parant] = cbtree[child];
}
parant = child;
}
cbtree[parant] = last_node;
return min_node;
}
private:
Node* *cbtree;
int size;
};
public:
HuffmanTree(int capacity) :heap(capacity), root(NULL), leaves(0), wpl(0) {
}
~HuffmanTree() {
for (size_t i = 0; i < nodes.size(); i++) {
delete nodes[i];
}
}
void Insert(int item) {
leaves++;
nodes.push_back(new Node(item));
heap.Insert(nodes.back());
}
int GetWeight(int leave) {
return nodes[leave]->weight;
}
int GetWPL() {
if (!root) {
Build();
}
if (wpl == 0) {
for (int i = 0; i < leaves; i++) {
int depth = 0;
for (Node* leave = nodes[i]; leave->parent; leave = leave->parent) {
depth++;
}
wpl += depth * nodes[i]->weight;
}
}
return wpl;
}
private:
Node* NextEmptyNode() {
static int next = leaves;
next++;
nodes[next] = new Node();
return nodes[next];
}
void Build() {
if (!root) {
nodes.resize(2 * leaves - 1);
for (int i = 0; i < leaves - 1; i++) {
Node* merged = NextEmptyNode();
merged->left = heap.DeleteMin();
merged->right = heap.DeleteMin();
merged->weight = merged->right->weight + merged->right->weight;
merged->right->parent = merged->left->parent = merged;
heap.Insert(merged);
}
root = heap.DeleteMin();
}
}
private:
MinHeap heap;
Node* root;
int leaves;
int wpl;
vector
nodes;
};
bool IsPrefixConflict(string codes[], int N) {
for (size_t i = 0; i < N; i++) {
for (size_t j = 0; j != i && j < N; j++) {
if (codes[j].find(codes[i]) == 0) {
return true;
}
}
}
return false;
}
int main() {
int N = 0;
cin >> N;
char c; int f;
HuffmanTree tree(N);
for (int i = 0; i < N; i++) {
cin >> c >> f;
tree.Insert(f);
}
int M = 0;
cin >> M;
for (size_t mstu = 0; mstu < M; mstu++) {
// save all the input codes
string codes[64];
for (size_t ncode = 0; ncode < N; ncode++) {
cin >> c >> codes[ncode];
}
// calculate the wpl of the codes
int wpl = 0;
for (int kcode = 0; kcode < N; kcode++) {
wpl += (codes[kcode].length() * tree.GetWeight(kcode));
}
// check prefix error and both wpl
if (!IsPrefixConflict(codes, N) && wpl == tree.GetWPL()) {
printf("Yes\n");
} else {
printf("No\n");
}
}
return 0;
}emptyemptyemptyemptyemptyemptyemptyempty
<script src="https://gist.github.com/Talentwill/f044055edc41e5fd0320e15e9034ceb0.js"></script>
#include
#include
#include
using namespace std;
class HuffmanTree {
struct Node {
Node(int w = 0) :weight(w), left(NULL), right(NULL), parent(NULL) {}
int weight;
Node* left;
Node* right;
Node* parent;
};
class MinHeap {
public:
MinHeap(int N) {
cbtree = new Node*[N + 1];
//set samllest guard
cbtree[0] = new Node(-1);
size = 0;
};
~MinHeap() {
delete cbtree[0];
cbtree[0] = NULL;
delete[] cbtree;
}
int Size() {
return size;
}
void Insert(Node* item) {
int i = ++size;
for (; item->weight < cbtree[i / 2]->weight; i = i / 2) {
cbtree[i] = cbtree[i / 2];
}
cbtree[i] = item;
return;
}
Node* DeleteMin() {
Node* min_node = cbtree[1]; // the minimun item
Node* last_node = cbtree[size]; // the last item
cbtree[size--] = NULL; //clear the last pointer
int child, parant = 1;
// loop until parant has no children
while (parant * 2 <= size) {
child = 2 * parant;
// has right child && get the minimun of them
if (child != size && cbtree[child + 1]->weight < cbtree[child]->weight) {
child++;
}
if (last_node->weight < cbtree[child]->weight) {
// item is less than its child, Ok
break;
} else {
// child is less then parent, move to parent
cbtree[parant] = cbtree[child];
}
parant = child;
}
cbtree[parant] = last_node;
return min_node;
}
private:
Node* *cbtree;
int size;
};
public:
HuffmanTree(int capacity) :heap(capacity), root(NULL), leaves(0), wpl(0) {
}
~HuffmanTree() {
for (size_t i = 0; i < nodes.size(); i++) {
delete nodes[i];
}
}
void Insert(int item) {
leaves++;
nodes.push_back(new Node(item));
heap.Insert(nodes.back());
}
int GetWeight(int leave) {
return nodes[leave]->weight;
}
int GetWPL() {
if (!root) {
Build();
}
if (wpl == 0) {
for (int i = 0; i < leaves; i++) {
int depth = 0;
for (Node* leave = nodes[i]; leave->parent; leave = leave->parent) {
depth++;
}
wpl += depth * nodes[i]->weight;
}
}
return wpl;
}
private:
Node* NextEmptyNode() {
static int next = leaves;
next++;
nodes[next] = new Node();
return nodes[next];
}
void Build() {
if (!root) {
nodes.resize(2 * leaves - 1);
for (int i = 0; i < leaves - 1; i++) {
Node* merged = NextEmptyNode();
merged->left = heap.DeleteMin();
merged->right = heap.DeleteMin();
merged->weight = merged->right->weight + merged->right->weight;
merged->right->parent = merged->left->parent = merged;
heap.Insert(merged);
}
root = heap.DeleteMin();
}
}
private:
MinHeap heap;
Node* root;
int leaves;
int wpl;
vector
nodes;
};
bool IsPrefixConflict(string codes[], int N) {
for (size_t i = 0; i < N; i++) {
for (size_t j = 0; j != i && j < N; j++) {
if (codes[j].find(codes[i]) == 0) {
return true;
}
}
}
return false;
}
int main() {
int N = 0;
cin >> N;
char c; int f;
HuffmanTree tree(N);
for (int i = 0; i < N; i++) {
cin >> c >> f;
tree.Insert(f);
}
int M = 0;
cin >> M;
for (size_t mstu = 0; mstu < M; mstu++) {
// save all the input codes
string codes[64];
for (size_t ncode = 0; ncode < N; ncode++) {
cin >> c >> codes[ncode];
}
// calculate the wpl of the codes
int wpl = 0;
for (int kcode = 0; kcode < N; kcode++) {
wpl += (codes[kcode].length() * tree.GetWeight(kcode));
}
// check prefix error and both wpl
if (!IsPrefixConflict(codes, N) && wpl == tree.GetWPL()) {
printf("Yes\n");
} else {
printf("No\n");
}
}
return 0;
}emptyemptyemptyemptyemptyemptyemptyempty