PTA 7-11 哈夫曼编码 (30 分)
给定一段文字,如果我们统计出字母出现的频率,是可以根据哈夫曼算法给出一套编码,使得用此编码压缩原文可以得到最短的编码总长。然而哈夫曼编码并不是唯一的。例如对字符串"aaaxuaxz",容易得到字母 ‘a’、‘x’、‘u’、‘z’ 的出现频率对应为 4、2、1、1。我们可以设计编码 {‘a’=0, ‘x’=10, ‘u’=110, ‘z’=111},也可以用另一套 {‘a’=1, ‘x’=01, ‘u’=001, ‘z’=000},还可以用 {‘a’=0, ‘x’=11, ‘u’=100, ‘z’=101},三套编码都可以把原文压缩到 14 个字节。但是 {‘a’=0, ‘x’=01, ‘u’=011, ‘z’=001} 就不是哈夫曼编码,因为用这套编码压缩得到 00001011001001 后,解码的结果不唯一,“aaaxuaxz” 和 “aazuaxax” 都可以对应解码的结果。本题就请你判断任一套编码是否哈夫曼编码。
先用优先队列求出最优长度,再判断符合最优长度的编码是否存在一个字母的编码是另一个字母的编码的前缀(如果存在这种情况,读取编码时无法确定何时结束,就不是有效编码)
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int sum=0;
bool Check(int *a,string *ss,int n)
{
int len=0;
string l,s;
int c;
for(int i=0; i<n; i++)
{
for(int j=i+1; j<n; j++)
{
c=min(ss[i].length(),ss[j].length());
if(ss[i].substr(0,c)==ss[j].substr(0,c))//检查是否存在一个编码是另一个编码的前缀
{
return false;
}
}
len+=a[i]*ss[i].length();
}
if(len!=sum)//如果长度不是最短长度
return false;
return true;
}
int main()
{
priority_queue<int,vector<int>,greater<int> > Q;
string ss[1001],s,code[1001];
int n,n2,a[1001],t=0;
cin>>n;
for(int i=0; i<n; i++)
{
cin>>ss[i];
cin>>a[i];
Q.push(a[i]);
}
while(Q.size()>1)//求最短编码的长度
{
t=0;
t+=Q.top();
Q.pop();
t+=Q.top();
Q.pop();
sum+=t;
Q.push(t);
}
cin>>n2;
for(int i=0; i<n2; i++)
{
for(int j=0; j<n; j++)
{
cin>>s;
cin>>code[j];
}
if(Check(a,code,n)==true)
{
cout<<"Yes"<<endl;
}
else
{
cout<<"No"<<endl;
}
}
return 0;
}