UOJ #9 vfk的数据 排序 字典序比较
2016-02-13 11:37
330 查看
UOJ #9 vfk的数据 排序
题目
描述
UOJ上,由于一群人开心的在hack着,有的题的测试数据都有1000010000组了!为了处理这些数据,vfk决定把这道题所有输入数据都弄出来,每个数据给个编号,比如uoj1.inuoj1.in,uoj2.inuoj2.in。
这些编号是随机的,可以不连续,比如三组数据分别叫uoj1.inuoj1.in, uoj100.inuoj100.in,uoj2014.inuoj2014.in。
输入数据的文件名一定是:题目名 + 数据编号 + “.in.in”。
vfk要你把这些输入文件按数据编号进行排序,之后用在线仙人球嵌套动态网络路径剖分优化的分支定界贪心剪枝启发式迭代加深人工智能搜索决策算法解决问题。
input
8dajiahaowoshiyangli9.in
dajiahaowoshiyangli5.in
dajiahaowoshiyangli2.in
dajiahaowoshiyangli1.in
dajiahaowoshiyangli3.in
dajiahaowoshiyangli7.in
dajiahaowoshiyangli6.in
dajiahaowoshiyangli8.in
output
dajiahaowoshiyangli1.indajiahaowoshiyangli2.in
dajiahaowoshiyangli3.in
dajiahaowoshiyangli5.in
dajiahaowoshiyangli6.in
dajiahaowoshiyangli7.in
dajiahaowoshiyangli8.in
dajiahaowoshiyangli9.in
限制与约定
测试点编号 | nn的规模 |
---|---|
11~55 | n≤100n≤100 |
66~1010 | n≤10000n≤10000 |
时间限制:1s1s
空间限制:256MB256MB
分析
直接排序。第一关键字:长度;
第二关键字:字典序;
时间复杂度为O(nLlogn)O(nL\log n)。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=32768; const int L=128; int n; struct P { char s[L]; int len; }p ; inline int operator < (P pa,P pb) { return pa.len!=pb.len?pa.len<pb.len:strcmp(pa.s,pb.s)<0; } int main(void) { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%s",p[i].s),p[i].len=strlen(p[i].s); sort(p+1,p+n+1); for (int i=1;i<=n;i++) printf("%s\n",p[i].s); return 0; }
其实数据范围加强,也是可以做的.
还是快排,优化字符串的比较方法.
对于两个字符串,我们先预处理处前缀Hash值,然后二分长度找到不相同的第一位。
时间复杂度优化为O(nlognlogL)O(n\log n\log L).
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef unsigned long long ulint; const int N=32768; const int L=128; const int M=257; int n; struct P { char s[L]; int len; ulint h[L]; inline void calc(void); }p ; inline void P::calc(void) { ulint mtp=1; h[1]=s[1]; for (int i=2;i<=len;i++) { mtp=mtp*M; h[i]=h[i-1]+mtp*s[i]; } } inline int operator < (P pa,P pb) { if (pa.len!=pb.len) return pa.len<pb.len; int l=0,r=pa.len,mid; for (;l<=r;) { mid=l+r>>1; pa.h[mid]==pb.h[mid]?l=mid+1:r=mid-1; } return pa.s[r+1]<pb.s[r+1]; } int main(void) { scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%s",&p[i].s[1]); p[i].len=strlen(&p[i].s[1]); p[i].calc(); } sort(p+1,p+n+1); for (int i=1;i<=n;i++) printf("%s\n",&p[i].s[1]); return 0; }
另外还可以使用Trie.
O(NL)O(NL).
小结
较大的数字的处理方法:①用字符串存储,注意不要误用int;
②注意比较数的大小的时候,首先要比较长度,然后再按字典序比较;
③涉及运算时要用数组倒着存,高精度模拟;
排序的常用方法:
①冒泡排序:针对小数据;
②快速排序/sort:普通数据;
③基数排序/Trie树排序:当元素的种类很少时考虑使用;
不要忽略方法①和方法③.
关于字典序比较的实现:
①strcmp,字典序逐位比较,O(L)O(L)
②若要多次比较,可以考虑预处理出前缀Hash值,然后二分+Hash找最多的相同位,再比较下一位.
预处理O(L)O(L),比较O(logL)O(\log L).
相关文章推荐
- chmod,fchmod,and fchmodat Functions
- vijos 1213:80人环游世界
- 顺序查找
- Prime Path(POJ 3126 BFS)
- android TextView 设置字体大小
- JS动态原型
- 关系型数据库是如何运作的
- 上传图片3.0--drp203
- java正则表达式提取xxxx(yyyy)中的内容
- HTML5のWeb SQL
- hdu 4771 Stealing Harry Potter's Precious(bfs)
- 新手学习Cocoapods教程
- Docker实践1:Virtualbox安装Oracle Enterprise Linux R6 U5
- poj2127Greatest Common Increasing Subsequence【LICS】
- 强悍书单:概率与测度论+数理统计+随机过程+金融
- 如何使用SHOW WARNINGS?
- ubuntu 开发板ping通虚拟机挂载nfs服务器
- 守望者的逃离
- 正交表达式
- Android无序广播案例