哈夫曼树

Yes 需满足两个条件:1.HuffmanTree 结构不同,但WPL一定。子串WPL需一致

          2.判断是否为前缀码

  开始判断用的strstr函数,但其传值应为char *,不能用在string类型。所以后来改用substr。

substr(start,length);start为子串起始位置,length为从起始位置的长度。

 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4 
 5 int main()
 6 { 
 7     string str = "123456",endStr;   
 8     endStr = str.substr(0,3);   
 9     cout<< endStr <<endl;  
10     return 0;
11 }
12 //output:123
View Eg Code

  因为这里用了容器优先队列,且判断前缀码用了暴力求解,substr(start,length);函数。所以 要点:最大N&M,code长度等于63  超时了。

  自己写,会快。

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 NNdistinct 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 MM student submissions. Each student submission consists of NN 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 <iostream>
 2 #include <cstdio>
 3 #include <string>
 4 #include <queue>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 struct HuffTreeNode
 9 {
10     char c;
11     int f;
12 };
13 struct HuffTreeNode HuffNode[65];
14 
15 struct strNod
16 {
17     char c;
18     string code;
19 };
20 struct strNod strNode[65];
21 
22 bool compare(strNod a, strNod b)
23 {
24     return a.code.size() < b.code.size();/*长度从小到大排序 */
25 }
26 
27 /*strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。
28 如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。*/
29 /*[Error] cannot convert 'std::string {aka std::basic_string<char>}' to 'const char*' for argument '1' to 'char* strstr(const char*, const char*)'*/
30 /*是子串返回true ,否则false */
31 bool isStrstr(int N)
32 {
33     sort(strNode, strNode+N, compare);
34     for(int i = 0; i < N; i ++) {
35         for(int j = i + 1; j < N; j++) {
36             if( strNode[j].code.substr( 0, strNode[i].code.size() ) == strNode[i].code )
37                 return true;
38         }
39     }
40     return false;
41 }
42 
43 int main()
44 {
45     int N;
46     scanf("%d",&N);
47     priority_queue<int, vector<int>, greater<int> > pq;
48     for(int i = 0; i < N; i++) {
49         getchar();        /*排除回车 空格的影响 */
50         scanf("%c",&HuffNode[i].c);
51         scanf("%d",&HuffNode[i].f);
52         pq.push(HuffNode[i].f);
53     }
54     /*计算HuffmanTree WPL*/
55     int WPL = 0;
56     int smallA,smallB;
57     while( !pq.empty() ) {
58         smallA = pq.top(); pq.pop();    /*取出两个最小的 */
59         if( !pq.empty() ) {
60             smallB = pq.top(); pq.pop();
61             smallA += smallB; 
62             pq.push(smallA);    /*求和后push进优先队列 */
63         }                
64         WPL += smallA;
65     }
66     WPL -= smallA;    /*求出WPL */
67 /*    printf("WPL = %d",WPL);*/
68     int M;
69     scanf("%d",&M);
70     for(int i = 0; i < M; i++) {
71         int checkWpl = 0;
72         for(int j = 0; j < N; j++) {
73             cin >> strNode[j].c >> strNode[j].code;
74             checkWpl += strNode[j].code.size() * HuffNode[j].f; //计算wpl 
75         }
76 /*        printf("checkWpl = %d",checkWpl);*/
77         if(checkWpl == WPL) {    /*WPL符合,判断是否是前缀 */
78             if( isStrstr(N) )    /*有子串,不符合 */
79                 printf("No\n");
80             else
81                 printf("Yes\n");
82         }
83         else
84             printf("No\n"); 
85     }
86     return 0;
87 } 

 

事实证明,自己写最小堆,并不能达到要求。大头应该是字符串比较那里。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 #define MINDATA 0  /* 该值应根据具体情况定义为小于堆中所有可能元素的值 */
  8 #define ERROR -1
  9 
 10 struct HNode {
 11     int *Data; /* 存储元素的数组 */
 12     int Size;          /* 堆中当前元素个数 */
 13     int Capacity;      /* 堆的最大容量 */
 14 };
 15 typedef struct HNode *MinHeap; /* 堆的类型定义 */
 16 
 17 struct TreeNode {
 18     char c;
 19     int f;
 20 };
 21 struct TreeNode HuffNode[65];
 22 
 23 struct strNod
 24 {
 25     char c;
 26     string code;
 27 };
 28 struct strNod strNode[65];
 29 MinHeap CreateHeap( int MaxSize );
 30 bool IsFull( MinHeap H );
 31 bool Insert( MinHeap H, int X );
 32 bool IsEmpty( MinHeap H );
 33 int DeleteMin( MinHeap H );
 34 
 35 bool compare(strNod a, strNod b)
 36 {
 37     return a.code.size() < b.code.size();/*长度从小到大排序 */
 38 }
 39 
 40 /*strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。
 41 如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。*/
 42 /*[Error] cannot convert 'std::string {aka std::basic_string<char>}' to 'const char*' for argument '1' to 'char* strstr(const char*, const char*)'*/
 43 /*是子串返回true ,否则false */
 44 bool isStrstr(int N)
 45 {
 46     sort(strNode, strNode+N, compare);
 47     for(int i = 0; i < N; i ++) {
 48         for(int j = i + 1; j < N; j++) {
 49             if( strNode[j].code.substr( 0, strNode[i].code.size() ) == strNode[i].code )
 50                 return true;
 51         }
 52     }
 53     return false;
 54 }
 55 
 56 int main()
 57 {
 58     int N;
 59     scanf("%d",&N);
 60     MinHeap Heap = CreateHeap(N);
 61     for(int i = 0; i < N; i++) {
 62         getchar();        /*排除回车 空格的影响 */
 63         scanf("%c",&HuffNode[i].c);
 64         scanf("%d",&HuffNode[i].f);
 65         Insert(Heap, HuffNode[i].f);
 66     }
 67     
 68     //计算WPL的值 
 69     int WPL = 0;
 70     int smallA, smallB;
 71     while( !IsEmpty(Heap) ) {
 72         smallA = DeleteMin(Heap);
 73         if( !IsEmpty(Heap) ) {
 74             smallB = DeleteMin(Heap);
 75             smallA += smallB;
 76             Insert( Heap, smallA);
 77         }
 78         WPL += smallA;    
 79     } 
 80     WPL -= smallA;    
 81 //    printf("WPL = %d\n",WPL);
 82 
 83     int M;
 84     scanf("%d",&M);
 85     for(int i = 0; i < M; i++) {
 86         int checkWpl = 0;
 87         for(int j = 0; j < N; j++) {
 88             cin >> strNode[j].c >> strNode[j].code;
 89             checkWpl += strNode[j].code.size() * HuffNode[j].f; //计算wpl 
 90         }
 91 /*        printf("checkWpl = %d",checkWpl);*/
 92         if(checkWpl == WPL) {    /*WPL符合,判断是否是前缀 */
 93             if( isStrstr(N) )    /*有子串,不符合 */
 94                 printf("No\n");
 95             else
 96                 printf("Yes\n");
 97         }
 98         else
 99             printf("No\n"); 
100     }
101     return 0;    
102 } 
103 
104 /* 创建容量为MaxSize的空的最小堆 */ 
105 MinHeap CreateHeap( int MaxSize )
106 { 
107  
108     MinHeap H = (MinHeap)malloc(sizeof(struct HNode));
109     H->Data = (int*)malloc((MaxSize+1)*sizeof(int));
110     H->Size = 0;
111     H->Capacity = MaxSize;
112     H->Data[0] = MINDATA; /* 定义"哨兵"为小于堆中所有可能元素的值*/
113     return H;
114 }
115 
116 bool IsFull( MinHeap H )
117 {
118     return (H->Size == H->Capacity);
119 }
120 
121 /* 将元素X插入最小堆H,其中H->Data[0]已经定义为哨兵 */ 
122 bool Insert( MinHeap H, int X )
123 {
124     if ( IsFull(H) ) { 
125         printf("最小堆已满");
126         return false;
127     }
128     int i = ++H->Size; /* i指向插入后堆中的最后一个元素的位置 */
129     for ( ; H->Data[i/2] > X; i /= 2 )
130         H->Data[i] = H->Data[i/2]; /* 上滤X */
131     H->Data[i] = X; /* 将X插入 */
132     return true;
133 }
134 
135 bool IsEmpty( MinHeap H )
136 {
137     return (H->Size == 0);
138 }
139 
140 /* 从最小堆H中取出键值为最小的元素,并删除一个结点 */ 
141 int DeleteMin( MinHeap H )
142 { 
143     int Parent, Child;
144     int MinItem, X;
145  
146     if ( IsEmpty(H) ) {
147         printf("最小堆已为空");
148         return ERROR;
149     }
150  
151     MinItem = H->Data[1]; /* 取出根结点存放的最小值 */
152     /* 用最小堆中最后一个元素从根结点开始向上过滤下层结点 */
153     X = H->Data[H->Size--]; /* 注意当前堆的规模要减小 */
154     for( Parent = 1; Parent * 2 <= H->Size; Parent = Child ) {
155         Child = Parent * 2;
156         if( (Child != H->Size) && (H->Data[Child] > H->Data[Child+1]) )
157             Child++;  /* Child指向左右子结点的较小者 */
158         if( X <= H->Data[Child] ) break; /* 找到了合适位置 */
159         else  /* 下滤X */
160             H->Data[Parent] = H->Data[Child];
161     }
162     H->Data[Parent] = X;
163  
164     return MinItem;
165 } 
View Code

 剪枝、。。。失败

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 #define MINDATA 0  /* 该值应根据具体情况定义为小于堆中所有可能元素的值 */
  8 #define ERROR -1
  9 
 10 struct HNode {
 11     int *Data; /* 存储元素的数组 */
 12     int Size;          /* 堆中当前元素个数 */
 13     int Capacity;      /* 堆的最大容量 */
 14 };
 15 typedef struct HNode *MinHeap; /* 堆的类型定义 */
 16 
 17 struct TreeNode {
 18     char c;
 19     int f;
 20 };
 21 struct TreeNode HuffNode[65];
 22 
 23 struct strNod
 24 {
 25     char c;
 26     string code;
 27 };
 28 struct strNod strNode[65];
 29 MinHeap CreateHeap( int MaxSize );
 30 bool IsFull( MinHeap H );
 31 bool Insert( MinHeap H, int X );
 32 bool IsEmpty( MinHeap H );
 33 int DeleteMin( MinHeap H );
 34 
 35 bool compare(strNod a, strNod b)
 36 {
 37     return a.code.size() < b.code.size();/*长度从小到大排序 */
 38 }
 39 
 40 /*strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。
 41 如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。*/
 42 /*[Error] cannot convert 'std::string {aka std::basic_string<char>}' to 'const char*' for argument '1' to 'char* strstr(const char*, const char*)'*/
 43 /*是子串返回true ,否则false */
 44 bool isStrstr(int N)
 45 {
 46     sort(strNode, strNode+N, compare);
 47     for(int i = 0; i < N; i ++) {
 48         for(int j = i + 1; j < N; j++) {
 49             if( strNode[j].code.substr( 0, strNode[i].code.size() ) == strNode[i].code )
 50                 return true;
 51         }
 52     }
 53     return false;
 54 }
 55 
 56 int main()
 57 {
 58     int N;
 59     scanf("%d",&N);
 60     MinHeap Heap = CreateHeap(N);
 61     for(int i = 0; i < N; i++) {
 62         getchar();        /*排除回车 空格的影响 */
 63         scanf("%c",&HuffNode[i].c);
 64         scanf("%d",&HuffNode[i].f);
 65         Insert(Heap, HuffNode[i].f);
 66     }
 67     
 68     //计算WPL的值 
 69     int WPL = 0;
 70     int smallA, smallB;
 71     while( !IsEmpty(Heap) ) {
 72         smallA = DeleteMin(Heap);
 73         if( !IsEmpty(Heap) ) {
 74             smallB = DeleteMin(Heap);
 75             smallA += smallB;
 76             Insert( Heap, smallA);
 77         }
 78         WPL += smallA;    
 79     } 
 80     WPL -= smallA;    
 81 //    printf("WPL = %d\n",WPL);
 82 
 83     int M;
 84     
 85     scanf("%d",&M);
 86     for(int i = 0; i < M; i++) {
 87         int checkWpl = 0;
 88         bool overFlag = false; //其中一个字符串超出长度 
 89         for(int j = 0; j < N; j++) {
 90             cin >> strNode[j].c >> strNode[j].code;
 91             if(strNode[j].code.size() > N-1) {    //如果有size超出N-1 一定不满足WPL 这里卡一刀希望快些
 92                  overFlag = true; 
 93                  break;
 94             }
 95             checkWpl += strNode[j].code.size() * HuffNode[j].f; //计算wpl 
 96         }
 97 /*        printf("checkWpl = %d",checkWpl);*/
 98         if(checkWpl == WPL && !overFlag) {    /*WPL符合,判断是否是前缀 */
 99             if( isStrstr(N) )    /*有子串,不符合 */
100                 printf("No\n");
101             else
102                 printf("Yes\n");
103         }
104         else
105             printf("No\n"); 
106     }
107     return 0;    
108 } 
109 
110 /* 创建容量为MaxSize的空的最小堆 */ 
111 MinHeap CreateHeap( int MaxSize )
112 { 
113  
114     MinHeap H = (MinHeap)malloc(sizeof(struct HNode));
115     H->Data = (int*)malloc((MaxSize+1)*sizeof(int));
116     H->Size = 0;
117     H->Capacity = MaxSize;
118     H->Data[0] = MINDATA; /* 定义"哨兵"为小于堆中所有可能元素的值*/
119     return H;
120 }
121 
122 bool IsFull( MinHeap H )
123 {
124     return (H->Size == H->Capacity);
125 }
126 
127 /* 将元素X插入最小堆H,其中H->Data[0]已经定义为哨兵 */ 
128 bool Insert( MinHeap H, int X )
129 {
130     if ( IsFull(H) ) { 
131         printf("最小堆已满");
132         return false;
133     }
134     int i = ++H->Size; /* i指向插入后堆中的最后一个元素的位置 */
135     for ( ; H->Data[i/2] > X; i /= 2 )
136         H->Data[i] = H->Data[i/2]; /* 上滤X */
137     H->Data[i] = X; /* 将X插入 */
138     return true;
139 }
140 
141 bool IsEmpty( MinHeap H )
142 {
143     return (H->Size == 0);
144 }
145 
146 /* 从最小堆H中取出键值为最小的元素,并删除一个结点 */ 
147 int DeleteMin( MinHeap H )
148 { 
149     int Parent, Child;
150     int MinItem, X;
151  
152     if ( IsEmpty(H) ) {
153         printf("最小堆已为空");
154         return ERROR;
155     }
156  
157     MinItem = H->Data[1]; /* 取出根结点存放的最小值 */
158     /* 用最小堆中最后一个元素从根结点开始向上过滤下层结点 */
159     X = H->Data[H->Size--]; /* 注意当前堆的规模要减小 */
160     for( Parent = 1; Parent * 2 <= H->Size; Parent = Child ) {
161         Child = Parent * 2;
162         if( (Child != H->Size) && (H->Data[Child] > H->Data[Child+1]) )
163             Child++;  /* Child指向左右子结点的较小者 */
164         if( X <= H->Data[Child] ) break; /* 找到了合适位置 */
165         else  /* 下滤X */
166             H->Data[Parent] = H->Data[Child];
167     }
168     H->Data[Parent] = X;
169  
170     return MinItem;
171 } 
View Code

 

posted on 2016-04-06 19:46  kuotian  阅读(740)  评论(0编辑  收藏  举报