7-1 哈夫曼编码 (30分)

简介: 7-1 哈夫曼编码 (30分)

7-1 哈夫曼编码 (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” 都可以对应解码的结果。本题就请你判断任一套编码是否哈夫曼编码。


输入格式:


首先第一行给出一个正整数 N(2≤N≤63),随后第二行给出 N 个不重复的字符及其出现频率,格式如下:


c[1] f[1] c[2] f[2] … c[N] f[N]


其中c[i]是集合{‘0’ - ‘9’, ‘a’ - ‘z’, ‘A’ - ‘Z’, ‘_’}中的字符;f[i]是c[i]的出现频率,为不超过 1000 的整数。再下一行给出一个正整数 M(≤1000),随后是 M 套待检的编码。每套编码占 N 行,格式为:


c[i] code[i]


其中c[i]是第i个字符;code[i]是不超过63个’0’和’1’的非空字符串。


输出格式:


对每套待检编码,如果是正确的哈夫曼编码,就在一行中输出"Yes",否则输出"No"。


注意:最优编码并不一定通过哈夫曼算法得到。任何能压缩到最优长度的前缀编码都应被判为正确。


输入样例:


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


输出样例:


Yes
Yes
No
No


题解


哈夫曼树需要满足两个性质,所有的哈夫曼编码的长度是唯一的,并且对于任何一个叶子结点,不会成为其他字符编码的前缀。在这道题中,哈夫曼树可以通过最小堆实现。小根堆每次弹出两个值,然后将两个值在插入小根堆中。


此问题中的哈夫曼编码长度用字符串长度乘出现的频率次数得到总长度,然后与最小堆求出来的哈夫曼编码长度比较进行判断是否为哈夫曼编码。用strstr函数判断是否为前缀。


代码


#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
char c[100];//字符
int f[1000];//频率
priority_queue<int, vector<int>, greater<int> > q; //代表小顶堆的优先对列
int main(void)
{
  int N;
  cin >> N;
  for (int i = 0; i < N; i++)
  {
    getchar();
    cin >> c[i] >> f[i];
    q.push(f[i]);   // 压入堆
  }
  int ans = 0;      //ans即为哈弗曼树带权路径长度和,也就是所对应的哈夫曼编码的长度
  while (q.size() > 1)
  {
    int x = q.top();
    q.pop();
    int y = q.top();
    q.pop();
    q.push(x + y);
    ans += x + y; //求哈夫曼编码的长度
  }
  int M;
  cin >> M;
  // 编码套数
  while (M--)
  {
    char code[66][66];
    int sum = 0;
    for (int j = 0; j < N; j++)
    {
      getchar();
      char C;
      cin >> C >> code[j];
      sum += strlen(code[j]) * f[j];//根据字符串长度以及出现的频率求出哈夫曼编码长度
    }
    if (sum != ans)
      printf("No\n");
    else // 相同判断前缀
    {
      int flag = 0;
      for (int j = 0; j < N; j++)
      {
        for (int l = 0; l < N; l++)
        {
          if (j != l)
          {
            if (strstr(code[l], code[j]) == &code[l][0])//查找字符串,如果找到了是相同前缀,就标记为No了
            {
              flag = 1;
              break;
            }
          }
        }
        if (flag == 1)break;
      }
      if (flag == 1)
        printf("No\n");
      else
        printf("Yes\n");
    }
  }
  return 0;
}
相关文章
overleaf 插入图片,引用图片,图标标题Fig与文章引用Figure不一致解决
overleaf 插入图片,引用图片,图标标题Fig与文章引用Figure不一致解决
11544 1
|
4月前
|
关系型数据库 MySQL PHP
WampServer安装教程(图文步骤)+ 下载+配置+解决图标红橙绿问题【附安装包】
WampServer是一款Windows下的免费PHP开发集成环境,支持快速搭建本地网站,适用于PHP+MySQL开发。安装简单,配置便捷,是运行WordPress、网站后台等项目的理想工具。(238字)
1118 4
|
Prometheus Kubernetes 监控
Prometheus 与 Kubernetes 的集成
【8月更文第29天】随着容器化应用的普及,Kubernetes 成为了管理这些应用的首选平台。为了有效地监控 Kubernetes 集群及其上的应用,Prometheus 提供了一个强大的监控解决方案。本文将详细介绍如何在 Kubernetes 集群中部署和配置 Prometheus,以便对容器化应用进行有效的监控。
1109 3
|
网络架构
YOLOv5改进 | 2023主干篇 | 利用RT-DETR特征提取网络PPHGNetV2改进YOLOv5(超级轻量化精度更高)
YOLOv5改进 | 2023主干篇 | 利用RT-DETR特征提取网络PPHGNetV2改进YOLOv5(超级轻量化精度更高)
826 0
|
Python
Python中的进制转换
Python中的进制转换
416 0
|
12月前
|
数据库 C++
【数据结构进阶】红黑树超详解 + 实现(附源码)
本文深入探讨了红黑树的实现原理与特性。红黑树是一种自平衡二叉搜索树,通过节点着色(红/黑)和特定规则,确保树的高度接近平衡,从而实现高效的插入、删除和查找操作。相比AVL树,红黑树允许一定程度的不平衡,减少了旋转调整次数,提升了动态操作性能。文章详细解析了红黑树的性质、插入时的平衡调整(变色与旋转)、查找逻辑以及合法性检查,并提供了完整的C++代码实现。红黑树在操作系统和数据库中广泛应用,其设计兼顾效率与复杂性的平衡。
2573 3
如何绘制PAD图和N-S图(详细步骤)
如何绘制PAD图和N-S图(详细步骤)
3254 0
|
存储 定位技术
【天梯赛】L2-048 寻宝图 (DFS做法)
遇到一个非'0'字符(也就是'1'和 宝藏'2'到'9')就让ans++,同时将这个非'0'字符染色为'0',然后往四个方向(上、下、左、右)搜索,这里的目的是那一片岛屿(也就是那一片为'1'的部分)都染色为‘0’。本题就请你统计一下,给定的地图上一共有多少岛屿,其中有多少是有宝藏的岛屿。为了判断有宝藏的岛屿,这里我开了一个全局变量f来判断这一片岛屿是否有宝藏(也就是有无字符'2'-'9'),当搜到字符'2'~'9'时就将f标记为1。在一行中输出 2 个整数,分别是岛屿的总数量和有宝藏的岛屿的数量。
368 5
|
数据库
1NF | 2NF | 3NF的区分以及什么是函数依赖、部分函数依赖、值传递依赖(最详细的讲解1NF、2NF、3NF的关系)
这篇文章详细讲解了数据库范式中的1NF、2NF和3NF,包括它们的定义、区分方法和如何判断部分函数依赖和传递函数依赖,以及如何将数据表规范化到相应的范式。
1NF | 2NF | 3NF的区分以及什么是函数依赖、部分函数依赖、值传递依赖(最详细的讲解1NF、2NF、3NF的关系)