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

UVa 283 Compress

题目分析本题要求实现一种特殊的变长编码压缩方法。在传统ASCII\texttt{ASCII}ASCII编码中每个字符使用固定的888位二进制数表示。为了进一步压缩数据我们希望给出现频率较高的字符分配较短的编码给出现频率较低的字符分配较长的编码。然而变长编码会引入一个严重的问题解码时无法确定字符的边界。例如若a编码为11e编码为1111那么比特序列111111既可以解释为ae也可以解释为ea或aaa。为了解决这个问题题目采用了一种特殊的编码规则所有需要编码的字符按照出现频率从高到低排序。编码采用类似前缀码的结构但扩展方式特殊当某一长度的编码全部使用完毕后最后一个编码作为“扩展标记”表示后续还有更多位。具体的编码分配过程如下长度为iii的编码共有2i2^i2i种可能。从最长的可用长度开始实际上题目是从长度111开始分配每次使用当前长度下的一个编码给一个字符。如果当前长度下的可用编码数大于等于剩余待编码字符数则直接分配完毕。否则最后一个编码作为扩展标记剩余字符继续用更长的编码表示。题目给出的例子中a、e、i、o、u、y六个字符被编码为长度222的编码a00e01i10最后一个长度222的编码11作为扩展标记长度444的编码o1100u1101y11101111空闲解题思路核心问题给定一段文本统计其中不同字符的出现频率按照上述编码规则求编码后文本的最小总比特数。关键观察频率顺序为了最小化总比特数出现频率高的字符应该获得尽可能短的编码因此需要将字符按频率从高到低排序。编码分配规则设共有mmm个不同字符。我们按长度递增的顺序分配编码长度为111的编码有2122^12212个0和1。若m1m 1m1则最后一个编码1必须作为扩展标记实际只能分配111个编码。剩余字符进入长度为222的编码空间但注意扩展标记占用了一个编码空间。更一般地设当前编码长度为lenlenlen则该长度下可用的编码数量为2len2^{len}2len减去之前已分配的编码数。但题目描述的规则实际上是另一种理解从长度i1i1i1开始设剩余待分配字符数为remainremainremain如果2i−1≥remain2^i - 1 \ge remain2i−1≥remain则所有剩余字符都可以用长度为iii的编码分配每个字符独占一个编码且不需要扩展标记。否则只能分配2i−12^i - 12i−1个编码给2i−12^i - 12i−1个字符最后一个编码作为扩展标记剩余字符进入更长的编码分配。为什么是2i−12^i - 12i−1长度为iii的二进制串共有2i2^i2i个。其中111个必须作为“扩展标记”保留所以实际可分配的只有2i−12^i - 12i−1个。实际分配过程排序后的字符按频率从高到低依次分配尽可能短的编码。对于频率列表counter[0...m-1]降序我们需要决定有多少字符获得长度为111的编码有多少字符获得长度为222的编码……而编码长度的分布必须满足对于每个长度iii分配的数量不超过2i−12^i - 12i−1并且长度递增。算法设计本题使用DFS\texttt{DFS}DFS回溯搜索所有可能的编码长度分配方案计算每种方案的总比特数取最小值。状态定义prefix当前已经分配的编码长度之和即已经用于表示前缀的比特数index当前已经处理到频率列表的第index个字符从000开始bits到目前为止已经计算的总比特数为什么搜索深度有限由于ASCII\texttt{ASCII}ASCII字符一共只有256256256种可能因此最多有256256256个不同字符。编码长度从111开始每次扩展增加当前长度但实际递归中prefix累计的是当前路径上所有“扩展标记”的长度之和。当prefix超过某个上限时搜索会自动剪枝因为next_bits已经超过当前最优解。频率统计与排序首先统计输入文本中每个字符的出现频率然后按频率降序排序。频率高的字符优先获得短编码这符合贪心思想。由于搜索会遍历所有可能的分配方案最终得到的一定是最优解。复杂度分析最多有256256256个不同字符。编码长度最大为888因为282562^825628256已经足够覆盖所有ASCII\texttt{ASCII}ASCII字符实际上在扩展标记的累积下编码长度可能超过888但每层递归prefix增长很快剪枝。搜索树的深度有限分支因子为888最坏情况下的状态数可控。代码实现// Compress// UVa ID: 283// Verdict: Accepted// Submission Date: 2016-06-03// UVa Run Time: 0.250s//// 版权所有C2016邱秋。metaphysis # yeah dot net#includebits/stdc.husingnamespacestd;vectorintcounter,codes(10);intminimalBits;// 深度优先搜索所有可能的编码长度分配方案// prefix: 当前已经分配的编码长度之和即扩展标记累积的比特数// index: 当前已经处理到频率列表中的第几个字符// bits: 到目前为止已经计算的总比特数voidbacktrack(intprefix,intindex,intbits){// 尝试所有可能的编码长度从1到8for(inti1;i8;i){// 如果当前长度下的编码总数2^i足以覆盖所有剩余字符if(indexcodes[i]counter.size()){intnext_bitsbits;// 剩余字符都使用长度为 (prefix i) 的编码for(intjindex;jcounter.size();j)next_bitscounter[j]*(prefixi);// 更新最优解minimalBitsmin(minimalBits,next_bits);}else{// 剩余字符数超过当前长度的编码总数// 只能分配 (codes[i] - 1) 个字符给当前长度// 最后一个编码作为扩展标记不分配给实际字符intnext_indexindex,next_bitsbits;for(intj1;jcodes[i];j)next_bitscounter[next_index]*(prefixi);// 剪枝如果当前累计比特数已经不小于已知最优解则不再继续搜索if(next_bitsminimalBits)backtrack(prefixi,next_index,next_bits);}}}intmain(intargc,char*argv[]){intcases;// 预处理长度为 i 的编码总数即 2^ifor(inti1;i8;i)codes[i]pow(2,i);string line;getline(cin,line);casesstoi(line);while(cases--){intn;getline(cin,line);nstoi(line);// 统计每个字符的出现频率mapchar,intfrequency;for(inti1;in;i){getline(cin,line);for(inti0;iline.length();i)frequency[line[i]];}// 将频率提取到 vector 中并按降序排序// 频率高的字符优先获得短编码counter.clear();for(autoitfrequency.begin();it!frequency.end();it)counter.push_back((*it).second);sort(counter.begin(),counter.end(),greaterint());// 初始化最优解为最大值开始深度优先搜索minimalBitsnumeric_limitsint::max();backtrack(0,0,0);coutminimalBitsendl;}return0;}
http://www.zskr.cn/news/1366987.html

相关文章:

  • 免费开源热物理计算工具CoolProp:工程师必备的热力学物性计算指南
  • 如何在5分钟内免费下载网页视频:VideoDownloadHelper完整指南
  • Win11Debloat:Windows 11终极优化指南,让你的电脑重获新生!
  • 如何免费在电脑上玩Switch游戏:yuzu模拟器终极简单指南
  • 对比官方原价Taotoken活动价带来的Token成本优势
  • 暗黑破坏神2存档编辑器:5分钟学会可视化修改角色与装备
  • 量子核方法基准测试:QKE与QKT在经典数据集上的表现与工程实践启示
  • 如何让百元对讲机拥有千元级专业功能:泉盛UV-K5/K6开源固件实战应用指南
  • 机器学习势函数结合自由能微扰:高效预测高熵合金熔点的混合计算框架
  • League Akari:英雄联盟玩家的终极智能助手工具包
  • 5步掌握CompressO:免费开源的终极视频压缩解决方案
  • 免费开源的Sales Dungeons:让热敏打印机成TTRPG实用工具,功能超丰富!
  • ACAV:支持 C、C++ 和 Objective-C 的交互式 AST 可视化工具,功能强大!
  • MeritOpt:动态权重聚合优化低资源语言多语言模型训练
  • 使用 Python 快速调用 Taotoken 多模型 API 的完整指南
  • Taotoken多模型聚合平台助力智能客服场景成本优化实践
  • HS2-HF Patch:让HoneySelect2游戏体验焕然一新的终极解决方案
  • 终极暗黑破坏神2优化方案:D2DX让你的经典游戏在现代PC上重获新生
  • Spring Boot 3.2 + JDK 21 虚拟线程压测:传统线程池与 Project Loom 的吞吐量对比实践
  • FanControl终极配置指南:5分钟实现Windows智能风扇控制与静音散热管理
  • 卡方检验筛选高质量样本,提升小样本学习在机器文本检测中的性能
  • Scroll Reverser:让macOS滚动方向随设备智能切换的终极方案
  • 对比直连与通过聚合平台调用ChatGPT的体验差异
  • 对比使用前后,Taotoken的用量看板让我的支出清晰可见
  • 终极指南:3分钟快速解锁QQ音乐加密音频的完整教程
  • 如何高效安装Adobe插件:ZXPInstaller终极指南
  • 别再瞎调参了!用Python实战Sensitivity Analysis,5分钟找出模型最怕哪个变量
  • 倾向性得分加权【9天实用统计学公益训练营Day4-3】
  • 倾向性得分方法【9天实用统计学公益训练营Day4-1】
  • 如何3分钟实现九大网盘下载加速:LinkSwift网盘直链解析工具终极指南