提高文件的压缩率一直是人们追求的目标。近几年有人提出了这样一种算法,它虽然只是单纯地对文件进行重排,本身并不压缩文件,但是对经这种算法调整后的文件进行压缩,在大多数情况下都能获得比原来更大的压缩率。
该算法具体如下:对一个长度为n的字符串S,首先根据它构造n个字符串,其中第i个字符串由S向左循环移位i-1次得到(见示例)。然后把这n个字符串按照首字符从小到大排序。如果两个字符串的首字符相同,则它们的相对位置不变。接着把排序后的字符串的尾字符依次连成一个新的字符串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、输出: S' = xelpame p = 7由于英语单词构造的特殊性,某些字母出现的频率很高,因此在 中相同的字母有很大几率排在一起,从而提高 的压缩率。虽然这种算法利用了英语单词的特性,然而在实践中,人们发现它几乎适用于所有类型的文件压缩。
请你编写一个程序模拟该算法的运行过程,输入字符串S,输出S'和p。
输入包含两行。第一行为一整数n,1<=n<=10000,表示S的长度;第二行为字符串S,字符串全部由小写字母组成,没有其它字符。
Output输出两行,第一行为S',第二行为整数p。
Sample Input7 exampleSample Output
xelpame 7
思路:构造的n个字符串首字母 就是输入的字符串。所以直接对输入的字符串进行排序, 首字母所在位置 就是该字符串第二个字符 经过排序后所在的位置。 每个字符与它的前一个字符首尾对应。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
int main(){
int n, flag = 1, loc;
map<char, queue<char> >p;
scanf("%d", &n);
char arr[n], ch;
scanf("%s", arr);
ch = arr[1]; //首字符在末尾时,字符串的第一个字符
if(arr[0] == arr[1]) flag = 2; //若前两个字符相同 则找排序后第二个ch,否则找第一个ch
for(int i = 0; i < n; i++){
queue<char> q;
if(i == 0){ //第一个字符与最后一个字符首位对应
q = p[arr[i]]; //每个首字符对应的尾字符,就是它在原字符串中的前一个
q.push(arr[n-1]);
p[arr[i]] = q;
}else{
q = p[arr[i]];
q.push(arr[i-1]);
p[arr[i]] = q;
}
}
sort(arr, arr+n);
for(int i = 0; i < n; i++){
queue<char> q;
if(ch == arr[i] && flag){
loc = i+1;
flag--;
}
q = p[arr[i]];
if(!q.empty()){
char c = q.front();
q.pop();
p[arr[i]] = q;
printf("%c", c);
}
}
printf("\n%d\n", loc);
return 0;
}