題意: 給定字母及其出現的頻率,可構建出相應的哈夫曼樹,先已知K個同學提交的哈弗曼編碼,問這些哈弗曼編碼是否是給出的哈夫曼樹的合法編碼。
tip:優先隊列算最小權值和、字典樹判斷query中是否存在前綴和編碼
#include <iostream>
#include <string>
#include<cstring>
#include <queue>
using namespace std;
int n,rc,c,d,num[300],k,flag;
string s,t;
int trie[10000][2],ind,en[10000];
void build(string str) {
int r = 0;
for(int i=0; i<str.size(); ++i) {
int e = str[i] - '0';
if(!trie[r][e]) {
trie[r][e] = ++ ind;
}
r = trie[r][e];
if(en[r] == 1) flag = 1;//存在公共前綴
if(i!=str.size()-1)
en[r] = 2;
}
if(en[r]) flag = 1;//存在公共前綴
en[r] = 1;
}
int main() {
scanf("%d",&n);
priority_queue<int,vector<int>,greater<int> > q;
for(int i = 0; i < n; i ++) {
cin>>s>>d;
num[(int)s[0]] = d;
q.push(d);
}
while(q.size() > 1) {//求出最小權值和
d = q.top();
q.pop();
d += q.top();
q.pop();
q.push(d);
rc += d;
}
cin>>k;
for(int i = 0; i < k; i ++) {
c = ind = flag = 0;
memset(trie,0,sizeof(trie));
memset(en,0,sizeof(en));
for(int j = 0; j < n; j ++) {
cin>>s>>t;
int len = t.size();
if(len >= n) flag = 1;
if(flag) continue;
build(t);
c += num[int(s[0])] * len;
}
printf("%s\n",c == rc && !flag ? "Yes" : "No");
}
}