当前位置: 首页 > news >正文

UVa 283 Compress

题目分析

本题要求实现一种特殊的变长编码压缩方法。在传统ASCII\texttt{ASCII}ASCII编码中,每个字符使用固定的888位二进制数表示。为了进一步压缩数据,我们希望给出现频率较高的字符分配较短的编码,给出现频率较低的字符分配较长的编码。

然而,变长编码会引入一个严重的问题:解码时无法确定字符的边界。例如,若a编码为11e编码为1111,那么比特序列111111既可以解释为ae,也可以解释为eaaaa

为了解决这个问题,题目采用了一种特殊的编码规则:

  1. 所有需要编码的字符按照出现频率从高到低排序。
  2. 编码采用类似前缀码的结构,但扩展方式特殊:当某一长度的编码全部使用完毕后,最后一个编码作为“扩展标记”,表示后续还有更多位。
  3. 具体的编码分配过程如下:
    • 长度为iii的编码共有2i2^i2i种可能。
    • 从最长的可用长度开始,实际上题目是从长度111开始分配,每次使用当前长度下的一个编码给一个字符。
    • 如果当前长度下的可用编码数大于等于剩余待编码字符数,则直接分配完毕。
    • 否则,最后一个编码作为扩展标记,剩余字符继续用更长的编码表示。

题目给出的例子中,aeiouy六个字符被编码为:

  • 长度222的编码:a=00e=01i=10
  • 最后一个长度222的编码11作为扩展标记
  • 长度444的编码:o=1100u=1101y=1110
  • 1111空闲

解题思路

核心问题

给定一段文本,统计其中不同字符的出现频率,按照上述编码规则,求编码后文本的最小总比特数。

关键观察

  1. 频率顺序:为了最小化总比特数,出现频率高的字符应该获得尽可能短的编码,因此需要将字符按频率从高到低排序。

  2. 编码分配规则:设共有mmm个不同字符。我们按长度递增的顺序分配编码:

    • 长度为111的编码有21=22^1=221=2个:01
    • m>1m > 1m>1,则最后一个编码1必须作为扩展标记,实际只能分配111个编码。
    • 剩余字符进入长度为222的编码空间,但注意扩展标记占用了一个编码空间。

    更一般地,设当前编码长度为lenlenlen,则该长度下可用的编码数量为2len2^{len}2len减去之前已分配的编码数。但题目描述的规则实际上是另一种理解:

    从长度i=1i=1i=1开始,设剩余待分配字符数为remainremainremain

    • 如果2i−1≥remain2^i - 1 \ge remain2i1remain,则所有剩余字符都可以用长度为iii的编码分配(每个字符独占一个编码,且不需要扩展标记)。
    • 否则,只能分配2i−12^i - 12i1个编码给2i−12^i - 12i1个字符,最后一个编码作为扩展标记,剩余字符进入更长的编码分配。
  3. 为什么是2i−12^i - 12i1:长度为iii的二进制串共有2i2^i2i个。其中111个必须作为“扩展标记”保留,所以实际可分配的只有2i−12^i - 12i1个。

  4. 实际分配过程:排序后的字符按频率从高到低,依次分配尽可能短的编码。对于频率列表counter[0...m-1](降序),我们需要决定:

    • 有多少字符获得长度为111的编码
    • 有多少字符获得长度为222的编码
    • ……

    而编码长度的分布必须满足:对于每个长度iii,分配的数量不超过2i−12^i - 12i1,并且长度递增。

算法设计

本题使用DFS\texttt{DFS}DFS回溯搜索所有可能的编码长度分配方案,计算每种方案的总比特数,取最小值。

状态定义

  • prefix:当前已经分配的编码长度之和(即已经用于表示前缀的比特数)
  • index:当前已经处理到频率列表的第index个字符(从000开始)
  • bits:到目前为止已经计算的总比特数

为什么搜索深度有限

由于ASCII\texttt{ASCII}ASCII字符一共只有256256256种可能,因此最多有256256256个不同字符。编码长度从111开始,每次扩展增加当前长度,但实际递归中prefix累计的是当前路径上所有“扩展标记”的长度之和。当prefix超过某个上限时,搜索会自动剪枝(因为next_bits已经超过当前最优解)。

频率统计与排序

首先统计输入文本中每个字符的出现频率,然后按频率降序排序。频率高的字符优先获得短编码,这符合贪心思想。由于搜索会遍历所有可能的分配方案,最终得到的一定是最优解。

复杂度分析

  • 最多有256256256个不同字符。
  • 编码长度最大为888,因为28=2562^8=25628=256已经足够覆盖所有ASCII\texttt{ASCII}ASCII字符(实际上在扩展标记的累积下,编码长度可能超过888,但每层递归prefix增长,很快剪枝)。
  • 搜索树的深度有限,分支因子为888,最坏情况下的状态数可控。

代码实现

// Compress// UVa ID: 283// Verdict: Accepted// Submission Date: 2016-06-03// UVa Run Time: 0.250s//// 版权所有(C)2016,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;vector<int>counter,codes(10);intminimalBits;// 深度优先搜索所有可能的编码长度分配方案// prefix: 当前已经分配的编码长度之和(即扩展标记累积的比特数)// index: 当前已经处理到频率列表中的第几个字符// bits: 到目前为止已经计算的总比特数voidbacktrack(intprefix,intindex,intbits){// 尝试所有可能的编码长度,从1到8for(inti=1;i<=8;i++){// 如果当前长度下的编码总数(2^i)足以覆盖所有剩余字符if(index+codes[i]>=counter.size()){intnext_bits=bits;// 剩余字符都使用长度为 (prefix + i) 的编码for(intj=index;j<counter.size();j++)next_bits+=counter[j]*(prefix+i);// 更新最优解minimalBits=min(minimalBits,next_bits);}else{// 剩余字符数超过当前长度的编码总数// 只能分配 (codes[i] - 1) 个字符给当前长度// 最后一个编码作为扩展标记,不分配给实际字符intnext_index=index,next_bits=bits;for(intj=1;j<codes[i];j++)next_bits+=counter[next_index++]*(prefix+i);// 剪枝:如果当前累计比特数已经不小于已知最优解,则不再继续搜索if(next_bits<minimalBits)backtrack(prefix+i,next_index,next_bits);}}}intmain(intargc,char*argv[]){intcases;// 预处理长度为 i 的编码总数,即 2^ifor(inti=1;i<=8;i++)codes[i]=pow(2,i);string line;getline(cin,line);cases=stoi(line);while(cases--){intn;getline(cin,line);n=stoi(line);// 统计每个字符的出现频率map<char,int>frequency;for(inti=1;i<=n;i++){getline(cin,line);for(inti=0;i<line.length();i++)frequency[line[i]]++;}// 将频率提取到 vector 中并按降序排序// 频率高的字符优先获得短编码counter.clear();for(autoit=frequency.begin();it!=frequency.end();it++)counter.push_back((*it).second);sort(counter.begin(),counter.end(),greater<int>());// 初始化最优解为最大值,开始深度优先搜索minimalBits=numeric_limits<int>::max();backtrack(0,0,0);cout<<minimalBits<<endl;}return0;}
http://www.jsqmd.com/news/877081/

相关文章:

  • 【进阶 v 2.7.5】Windows 系统 Open Claw 一站式部署教程
  • 基于AI的抄袭检测:从语义理解到代码分析的混合智能系统
  • 高铬钢丸厂家选购指南:如何选到靠谱稳定的供应商 - 资讯纵览
  • 机器学习防御组合冲突检测:DefCon框架原理与实践指南
  • 上海汽车音响改装终极天花板:魔都之声 25 大无人能及优势全揭秘,为什么它是全国音改界的 最后一站 - 汽车音响改装
  • GitHub 5天狂揽19k Star,这款开源AI编程助手杀疯了
  • 融合机器学习与人群动力学:构建公共安全智能预警系统
  • 3分钟搞定Mac Boot Camp驱动部署:Brigadier自动化终极指南
  • 柳州黄金回收星级口碑榜,福运来实力领跑 - 黄金回收
  • 算法竞赛党必备:用Friedman检验和Nemenyi后续检验给你的模型排名次(附Python代码)
  • 趣图:“代码明明是用手敲的,为什么要叫脚本?” 高赞回复太搞笑了
  • 2026 中国 GEO 优化服务商专业度 TOP5 深度评测:五大头部公司选型 - 资讯纵览
  • DS4Windows:让PS4手柄在PC平台焕发新生的终极解决方案
  • 5分钟极速备份:B站缓存视频永久保存完整指南
  • 2026年5月丽水黄金回收参考,福运来免费上门服务实测 - 黄金回收
  • 基于BERT的科研评审文本多标签分类:从数据标注到模型优化的完整实践
  • 79万中文医疗对话数据集:构建智能医疗问答系统的实战指南
  • 2026年4月河北有实力的氢氧化钠回收公司口碑推荐,国内氢氧化钠回收公司,氧化锆珠,耐腐蚀性强使用寿命长 - 品牌推荐师
  • 终极FanControl中文设置指南:5分钟让Windows风扇控制说中文,实现精准散热管理
  • Applite终极指南:告别命令行,用图形化界面轻松管理你的Mac应用
  • MeritOpt:动态权重聚合优化低资源语言多语言模型训练
  • 如何免费将模糊图片变高清:5个专业AI图像增强技巧
  • 企业形象照技术规格完全指南:从拍摄参数到交付标准
  • NLP文本预处理全流程解析:从TF-IDF到多模态与领域自适应
  • 终极ZeroOmega代理管理指南:3分钟掌握多代理智能切换
  • 合规经营深耕通信服务 黑龙江移远科技有限公司以全链条能力赋能对讲机全场景需求 - 黑龙江单工科技
  • 突破4:3限制:Rust内存注入技术实现《植物大战僵尸》宽屏革命
  • Mac Mouse Fix 终极配置指南:让普通鼠标实现专业级操作体验
  • Betaflight实时调度重构:如何通过Azure RTOS实现飞控系统性能突破
  • Topit窗口置顶神器:告别窗口遮挡烦恼,让Mac多任务效率翻倍