咳,對於不會建樹也懶得建樹的我。看到網上上百行建樹的題解就頭疼。所以我一直在想如何不建樹AC掉這道題,還好。。沒白花時間。。。
首先要清楚哈夫曼編碼的概念,我想能做L3的人底子應該不太差,哈夫曼的原理肯定都知道,我就不再贅述了。
但是做這道題還是要知道哈夫曼編碼的特徵或者性質。
1.編碼後路徑權值如何求?
其實哈夫曼編碼類似於貪心,每次取最小和次最小的,將他倆合併。以此類推到最後全部合併完成,我這裏用到了優先隊列,這樣合併完之後也就得到了權值。
2.編碼方式是否合法?
如果下面給的編碼長度和你求出來的哈夫曼編碼長度不同,那肯定不是。
如果相同,你還要判斷這樣編碼是否合法。就是每一個短碼都不能是其他編碼的前綴,這個也比較好判斷。
利用上面兩個性質(特徵),代碼也就不難寫出來:
#include<bits/stdc++.h>
using namespace std;
int n,k,val;
string str[10010];
map<char,int>m;
bool check()
{
sort(str,str+n);
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
if(str[j].substr(0,str[i].size())==str[i]) return false;
return true;
}
int main()
{
cin>>n;
priority_queue<int,vector<int>,greater<int>>q;
for(int i=0;i<n;i++)
{
char c;int x;
cin>>c>>x;
m[c]=x; q.push(x);
}
while(1)
{
int tp=q.top();q.pop();
if(q.empty()) break;
tp+=q.top();q.pop();
q.push(tp);
val+=tp;
}
cin>>k;
while(k--)
{
int len=0,flag=0;
for(int i=0;i<n;i++)
{
char c;
cin>>c>>str[i];
len+=m[c]*str[i].size();
}
if(len==val&&check()) puts("Yes");
else puts("No");
}
}