LG-P1124 文件压缩

P1124 文件压缩

题目背景

提高文件的压缩率一直是人们追求的目标。近几年有人提出了这样一种算法,它虽然只是单纯地对文件进行重排,本身并不压缩文件,但是经这种算法调整后的文件在大多数情况下都能获得比原来更大的压缩率。

题目描述

该算法具体如下:对一个长度为n的字符串S,首先根据它构造n个字符串,其中第i个字符串由将S的前i-1个字符置于末尾得到。然后把这n个字符串按照首字符从小到大排序,如果两个字符串的首字符相等,则按照它们在S中的位置从小到大排序。排序后的字符串的尾字符可以组成一个新的字符串S’,它的长度也是n,并且包含了S中的每一个字符。最后输出S’以及S的首字符在S’中的位置p。举例:

S:example

1、构造n个字符串

example

xamplee

ampleex

mpleexa

pleexam

leexamp

eexampl

2、将字符串排序

ampleex

example

eexampl

leexamp

mpleexa

pleexam

xamplee

3、压缩结果

xelpame S’

7 p

由于英语单词构造的特殊性,某些字母对出现的频率很高,因此在S’中相同的字母有很大几率排在一起,从而提高S’的压缩率。虽然这种算法利用了英语单词的特性,然而在实践的过程中,人们发现它几乎适用于所有的文件压缩。

请你编一个程序,读入S’和p,输出字符串S。

输入格式:
输入文件共有三行,第1行是一个整数n(1<=n<=10000),代表S’的长度,第2行是字符串S’,第3行是整数p。

输出格式:
仅包含一行S。

输入样例:
7
xelpame
7
输出样例:
example
题解:
这题其实看似很复杂,看似完全没有头绪,其实如果我们仔细读题,会注意到这样一件事情,就是把我们得到的 s’ 中字母排序后得到的 L,每位是对应 s’ 的字母为结尾的字符串的第一位。可能没太听懂,来颗栗子:

初始字符串为 bca
生成 bca,cab,abc
排序 abc,bca,cab
所以输入数据是:3 cab 3
cab 排序后 abc
生成的串排序后 a-c,b-a,c-b,中间的减号为省略部分,很明显正好组成了每个生成字符串的头和尾,而头和尾正好又是相邻关系(如果看成环),由此我们可以通过第一个推出所有的。

我是倒着推的。也就是第一个确定后,到 L 中寻找第一个(最前面的,后面的“最后一个”同理)相同的字母,实际上就是第一个字母(因为题目中说如果第一个大小相等按照原顺序),那么 it 对应的尾巴(called now)就是最后一个,接下来,在 L 中找最后一个和 now 相同的字母,这个字母同样也就是 now ,那么 it 对应的尾巴就是 倒数第二个……

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=10005;
int n,p,tt;
char s[maxn],L[maxn],ans[maxn];
int main()
{
    scanf("%d%s%d",&n,s+1,&p);
    for (int i=1;i<=n;i++) L[i]=s[i];
    sort(L+1,L+n+1);
    int now=p;ans[1]=s[p];tt=n;L[p]='?';//第一个对应头的必然是最后一个,但是后面处理方式的缘故,必须杀掉,否则可能导致求得的字符串短了一大截
//  printf("%d %d\n%s\n%s\n",n,p,s+1,L+1);
    for (int i=1;i<n;i++)
    {
        if (i<2) for (int j=1;j<=n;j++)
            {if (L[j]==s[now]) {L[j]='?';now=j;break;}}//如果是第一个,那么肯定找最前面那个相同的,否则找最后的。找到后要杀掉,否则后面会误判的。
        else for (int j=n;j;j--)
            {if (L[j]==s[now]) {L[j]='?';now=j;break;}}
        ans[n-i+1]=s[now];
    }
    for (int i=1;i<=n;i++) putchar(ans[i]);
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值