P1124文件压缩-字符串模拟

题目链接

题目背景

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

题目描述

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

S:example

1、构造 n n 个字符串

example

xamplee

ampleex

mpleexa

pleexam

leexamp

eexampl

2、将字符串排序

ampleex

example

eexampl

leexamp

mpleexa

pleexam

xamplee

3、压缩结果

xelpame x e l p a m e S S

7 7 p p

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

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

输入输出格式

输入格式:

共三行。

第一行是一个整数 n(1n10000) n ( 1 ≤ n ≤ 10000 ) ,代表 S S ’的长度。

第二行是字符串 S S ’。

第三行是整数 p p

输出格式:

一行,S。

输入输出样例

输入样例#1: 复制
7
xelpame
7
输出样例#1: 复制
example



这道题比较细致,需要慢慢地思考找规律,非常容易出错。找了几个题解之后细致比较知道了正解:

copy一下字符数组orig数组,然后排个序(从大到小)变成srt数组
利用给出地p按顺序遍历srt找到第一个等于orig[p]的,其对应的字符就是压缩前字符串的最后一个字符,然后倒着遍历srt数组,找到第一个等于该字符的,其对应的字符就是倒数第二个字符,不断这样寻找,直到逆序地找出整个字符串。

为什么刚开始要顺序而后来是逆序呢?这是因为开始查找的是第一个字符,由于排序的原因,和它相同的字符都在它之后,所以找到顺序第一个。而后面的查找由于是从后往前查找,所以同理的,应该找到逆序第一个。

这种方法是倒序查找,那么可不可以顺序查找呢?
我认为是不可以的。因为之所以倒叙查找可行,是因为压缩时有如果两个字符串的首字符相等,则按照它们在SS中的位置从小到大排序这个规则,而顺序由于是找压缩后的顺序,但由于右边的字符没有满足这个规则,所以顺序是不确定的。也就是说在某些题目里面可以是正确的,但在大多数题目里是不符合要求的。

参考链接

参考代码

#include 
#include 
using namespace std;

int main()
{
    int n, p;
    cin >> n;
    char orig[10005], srt[10005];
    for (int i = 1; i <= n; ++i) {
        cin >> orig[i];
        srt[i] = orig[i];
    }
    sort(srt + 1, srt + n + 1);
    cin >> p;
    char ans[10005];
    char c = orig[p];
    bool vis[10005] = {};
    for (int i = 1; i <= n; ++i) {
        if (c == srt[i]) {
            c = orig[i];
            vis[i] = true;
            break;
        }
    }
    int cnt = 0;
    ans[++cnt] = c;
    for (int i = n; i > 0; --i) {
        if (!vis[i] && c == srt[i]) {
            c = orig[i];
            //cout << c;
            vis[i] = true;
            ans[++cnt] = c;
            i = n + 1;
        }
    }
    for (int i = cnt; i > 0; --i) {
        cout << ans[i];
    }
}
/*
7
xelpame
7
*/

你可能感兴趣的:(弃用的分类:c++,字符串算法,模拟)