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

UVa 612 DNA Sorting

题目描述

序列中的“无序度”可以用逆序对的数量来衡量。例如,字母序列DAABEC中,D大于其右侧的四个字母,E大于其右侧的一个字母,因此逆序数为555。序列AACEDGG仅有一个逆序对(ED),几乎有序;而ZWQM666个逆序对,是完全逆序的。

你需要对一组DNA\texttt{DNA}DNA字符串(仅包含ACGT四种字符)进行排序,但不是按字母顺序,而是按“有序程度”从“最有序”到“最无序”排列。所有字符串长度相同。若两个字符串逆序数相同,则保持它们在输入中的相对顺序。

输入格式

第一行为一个整数MMM,表示数据集的个数。接下来每个数据集的第一行包含两个整数:nnn0<n≤500 < n \le 500<n50)表示字符串长度,mmm0<m≤1000 < m \le 1000<m100)表示字符串个数。随后mmm行,每行一个长度为nnn的字符串(仅含ACGT)。不同数据集之间可能存在空行,但cin可以忽略空白字符。

输出格式

对于每个数据集,输出mmm行,每行一个字符串,按逆序数从小到大排列。若逆序数相同,保持输入顺序。不同数据集的输出之间用一个空行分隔。

样例

输入

1 10 6 AACATGAAGG TTTTGGCCAA TTTGGCCAAA GATCAGATTT CCCGGGGGGA ATCGATGCAT

输出

CCCGGGGGGA AACATGAAGG GATCAGATTT ATCGATGCAT TTTTGGCCAA TTTGGCCAAA

题目分析

本题的核心是计算每个字符串的逆序数,并按逆序数升序排序。逆序数的定义:在一个序列中,如果一对字符i<ji < ji<jsi>sjs_i > s_jsi>sj(按字符ASCII\texttt{ASCII}ASCII码大小比较),则构成一个逆序对。由于字符串长度n≤50n \le 50n50,直接使用两层循环枚举所有字符对即可在O(n2)O(n^2)O(n2)时间内算出逆序数,总复杂度O(m⋅n2)O(m \cdot n^2)O(mn2),完全可行。

排序时需要保持逆序数相同元素的原始顺序,因此应使用稳定排序算法(如stable_sort)。这与样例中逆序数相同的字符串保持原输入顺序的要求一致。

解题思路

  1. 读入MMM表示数据集个数。
  2. 对于每个数据集:
    • 读入nnnmmm
    • 循环mmm次,读入每个字符串。
    • 对每个字符串,通过两层循环统计逆序数:对于iii000n−1n-1n1jjji+1i+1i+1n−1n-1n1,若line[j] < line[i],则逆序数加111
    • 将字符串和其逆序数存入结构体数组。
    • 使用stable_sort按逆序数升序排序。
    • 按排序后的顺序输出字符串。
    • 若非最后一个数据集,输出一个空行(即相邻数据集间空行)。

复杂度分析

  • 每个字符串计算逆序数:O(n2)O(n^2)O(n2)n≤50n \le 50n50,常数很小。
  • 排序:O(mlog⁡m)O(m \log m)O(mlogm)m≤100m \le 100m100
  • 总时间复杂度:O(M⋅m⋅n2)O(M \cdot m \cdot n^2)O(Mmn2)MMM未知但通常较小,完全可接受。
  • 空间复杂度:O(m)O(m)O(m),用于存储字符串和逆序数。

代码实现

// DNA Sorting// UVa ID: 612// Verdict: Accepted// Submission Date: 2016-08-23// UVa Run Time: 0.030s//// 版权所有(C)2016,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;structitem{string dna;intinversion;booloperator<(constitem&another)const{returninversion<another.inversion;}};intgetInversion(string&line){intinversion=0;for(inti=0;i<line.length();i++)for(intj=i+1;j<line.length();j++)if(line[j]<line[i])inversion++;returninversion;}intmain(){cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);intcases=0,n,m;cin>>cases;vector<item>dnas;for(intc=1;c<=cases;c++){dnas.clear();if(c>1)cout<<'\n';cin>>n>>m;cin.ignore(1024,'\n');string line;for(inti=0;i<m;i++){getline(cin,line);dnas.push_back((item){line,getInversion(line)});}stable_sort(dnas.begin(),dnas.end());for(autodata:dnas)cout<<data.dna<<'\n';}return0;}

总结

本题是一个典型的排序应用题,核心在于正确计算逆序数并利用稳定排序保证相同逆序数的字符串保持原顺序。由于数据规模极小,直接暴力计算即可。该题也提醒我们,在排序时若需保持相等元素的原始顺序,应当使用稳定排序算法(如stable_sort),而不是普通sort。此解法简洁高效,适合作为入门级排序与模拟练习题。

http://www.jsqmd.com/news/1088185/

相关文章:

  • Go语言Goroutine最佳实践:从并发基础到高性能实战
  • E-Hentai下载器:免费批量下载画廊图片的完整解决方案
  • 高性能计算中NVLink与加速器互联技术解析
  • 多模态AI的本质是张量代数:从线性映射到图文检索
  • RA8D2 VIN模块硬件加速配置:色彩空间转换与图像缩放实战详解
  • B站会员购抢票终极指南:5步从零开始轻松抢到心仪票务
  • COMTool架构深度解析:如何构建跨平台调试工具的设计哲学
  • GPT-5.6受限发布,海外AI监管升级,国产大模型迎来破局机遇?
  • Renesas Smart Configurator实战:图形化配置RZ/G MPU引脚与DDR内存
  • 嵌入式开发硬件沙盒:RH850/U2A评估板电源、时钟与跳线配置实战
  • 枣庄高口碑黄金铂金回收白银回收实体老店排行 5 家靠谱门店电话地址全收录
  • ARMv8内存属性探秘:从Normal到Device的架构设计与实战考量
  • Java计算机毕设之基于 SpringBoot 的房源信息管理及租房系统的设计与实现 轻量化同城租房服务管理系统(完整前后端代码+说明文档+LW,调试定制等)
  • 人生是一个动态平衡的系统的庖丁解牛
  • Rsysstat错误处理与日志系统:保证监控稳定性的关键
  • 实时操作系统(RTOS)的核心认知基石
  • openEuler网络优化技术:Gazelle高性能网络框架使用详解
  • 云原生CI/CD:从代码提交到生产部署的“高速公路“,Tekton + ArgoCD:构建云原生DevOps流水线
  • 终极指南:3步解决GitHub下载慢的免费加速插件
  • Plain Craft Launcher 2:智能高效的Minecraft游戏管理解决方案
  • Allegro多逻辑器件Annotate报错解析:Package属性配置与位号重分配实战
  • ncmdumpGUI:3步解锁网易云音乐加密文件的终极方案
  • Web安全基石:深入理解XSS攻击原理、类型与纵深防御策略
  • Hermes官方桌面版发布了
  • 面包板布线选线指南:从新手到高手的导线进化论
  • 微信语音转换终极指南:5分钟掌握silk-v3-decoder音频格式转换
  • 量子优化技术在无线通信中的应用与实践
  • 1G 回忆录:一块砖头改变世界的故事
  • LLCOM串口调试工具技术深度解析:Lua自动化与多协议融合的创新应用指南
  • MPU6050 DMP自检与倾斜检测实战避坑指南