pta5-9 Huffman Codes (30分)

5-9 Huffman Codes   (30分)

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 (2N63), 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

 

方法一:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<stack>
 5 #include<set>
 6 #include<map>
 7 #include<queue>
 8 #include<algorithm>
 9 using namespace std;
10 struct node{
11     string dight;
12     int weight;
13     bool operator<(const node &a) const {//什么情况下优先输出后面那个,这个和sort的刚好相反
14         if(weight==a.weight){
15             /*if(dight.length()==a.dight.length()){
16                 return dight.compare(a.dight)>0;
17             }*/
18             return dight.length()<a.dight.length();
19         }
20         return weight>a.weight;
21     }
22 };
23 node h[100];
24 map<char,int> ha;
25 int main(){
26     //freopen("D:\\INPUT.txt","r",stdin);
27     int n;
28     scanf("%d",&n);
29     int i,num,sum;
30     char cha;
31     for(i=0;i<n;i++){
32         cin>>cha;
33         scanf("%d",&ha[cha]);
34     }
35     scanf("%d",&num);
36     while(num--){
37         sum=0;
38         priority_queue<node> q;
39         for(i=0;i<n;i++){
40             cin>>cha>>h[i].dight;
41             //scanf("%s",h[i].dight);
42             sum+=ha[cha];
43             h[i].weight=ha[cha];
44             q.push(h[i]);
45         }
46         /*while(!q.empty()){
47             cout<<q.top().weight<<" "<<q.top().dight<<endl;
48             q.pop();
49         }*/
50         //cout<<num<<" "<<sum<<endl;
51         node cur,next;
52         queue<node> qq;
53         bool can;
54         while(!q.empty()){
55             cur=q.top();
56             q.pop();
57             can=false;
58             while(!q.empty()){
59                 next=q.top();
60                 q.pop();
61                 if(cur.dight.length()==next.dight.length()){
62                    if(cur.dight.substr(0,cur.dight.length()-1)==next.dight.substr(0,next.dight.length()-1)&&cur.dight[cur.dight.length()-1]!=next.dight[next.dight.length()-1]){
63                         can=true;
64                         while(!qq.empty()){//还原
65                             q.push(qq.front());
66                             qq.pop();
67                         }
68                         break;
69                    }
70                    else{
71                         qq.push(next);
72                    }
73                 }
74                 else{
75                     break;
76                 }
77             }
78             if(can){//找到了
79                 cur.dight=cur.dight.substr(0,cur.dight.length()-1);
80                 cur.weight+=next.weight;
81                 if(q.empty()){
82                    break;
83                 }
84                 q.push(cur);
85             }
86             else{
87                 break;
88             }
89         }
90         if(can&&cur.weight==sum&&!cur.dight.length()){
91             printf("Yes\n");
92         }
93         else{
94             printf("No\n");
95         }
96     }
97     return 0;
98 }

 

 

方法二:

学习网址:http://blog.csdn.net/u013167299/article/details/42244257

1.哈夫曼树法构造的wpl最小。

2.任何01字符串都不是其他字符串的前缀。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<stack>
 5 #include<set>
 6 #include<map>
 7 #include<queue>
 8 #include<algorithm>
 9 using namespace std;
10 struct node{
11     string s;
12     int count;
13 };
14 node p[80];
15 map<char,int> ha;
16 priority_queue<int,vector<int>,greater<int> > q;//从小到大排
17 bool check(node *p,int n){
18     int i,j;
19     for(i=0;i<n;i++){
20         string temp=p[i].s.substr(0,p[i].s.length());
21         for(j=0;j<n;j++){
22             if(i==j){
23                 continue;
24             }
25             if(temp==p[j].s.substr(0,p[i].s.length())){//前缀检查
26                 break;
27             }
28         }
29         if(j<n){//不满足要求
30             return false;
31         }
32     }
33     return true;
34 }
35 int main(){
36     //freopen("D:\\INPUT.txt","r",stdin);
37     int n,i;
38     scanf("%d",&n);
39     char c;
40     int wpl=0;
41     for(i=0;i<n;i++){
42         cin>>c;
43         scanf("%d",&ha[c]);
44         q.push(ha[c]);
45     }
46     int cur,next;
47     while(!q.empty()){
48         cur=q.top();
49         q.pop();
50         if(q.empty()){//最后一次不用做加法
51             break;
52         }
53         cur+=q.top();
54         q.pop();
55         wpl+=cur;
56 
57         //cout<<cur<<endl;
58 
59         q.push(cur);
60     }
61     //cout<<wpl<<endl;
62     int num;
63     scanf("%d",&num);
64     while(num--){
65         int sum=0;
66         for(i=0;i<n;i++){
67             cin>>c;
68             p[i].count=ha[c];
69             cin>>p[i].s;
70             sum+=p[i].count*p[i].s.length();
71         }
72 
73 //        cout<<sum<<endl;
74 
75         if(sum==wpl&&check(p,n)){
76             printf("Yes\n");
77         }
78         else{
79             printf("No\n");
80         }
81     }
82     return 0;
83 }

 

posted @ 2015-09-11 18:09  Deribs4  阅读(1224)  评论(0编辑  收藏  举报