1031: [JSOI2007]字符加密Cipher
Time Limit: 10 Sec Memory Limit: 162 MB Submit: 7384 Solved: 3198 [Submit][Status][Discuss]Description
喜欢钻研问题的JS同学,最近又迷上了对加密方法的思考。一天,他突然想出了一种他认为是终极的加密办法
:把需要加密的信息排成一圈,显然,它们有很多种不同的读法。例如下图,可以读作:
JSOI07 SOI07J OI07JS I07JSO 07JSOI 7JSOI0把它们按照字符串的大小排序:07JSOI 7JSOI0 I07JSO JSOI07
OI07JS SOI07J读出最后一列字符:I0O7SJ,就是加密后的字符串(其实这个加密手段实在很容易破解,鉴于这是
突然想出来的,那就^^)。但是,如果想加密的字符串实在太长,你能写一个程序完成这个任务吗?
Input
输入文件包含一行,欲加密的字符串。注意字符串的内容不一定是字母、数字,也可以是符号等。
Output
输出一行,为加密后的字符串。
Sample Input
JSOI07
Sample Output
I0O7SJ
HINT
对于100%的数据字符串的长度不超过100000。
把原串$S$复制一遍放在后面变为$SS$,求出$SS$的后缀数组,然后按序输出即可
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 200000 + 10;int sa[maxn], rank[maxn], tp[maxn], tax[maxn];int n, m;char s[maxn];inline void Rsort(){ ???for(int i = 0; i <= m; i++) tax[i] = 0; ???for(int i = 1; i <= n; i++) tax[rank[tp[i]]]++; ???for(int i = 1; i <= m; i++) tax[i] += tax[i - 1]; ???for(int i = n; i; i--) sa[tax[rank[tp[i]]]--] = tp[i];}bool inline cmp(int *a, int l, int r, int w){ ???return a[l] == a[r] && a[l + w] == a[r + w]; }void suffix(){ ???m = 127; ???for(int i = 1; i <= n; i++){ ???????rank[i] = s[i]; ???????tp[i] = i; ???} ???Rsort(); ???for(int p, w = 1; p < n; w <<= 1, m = p){ ???????p = 0; ???????for(int i = n - w + 1; i <= n; i++) tp[++p] = i; ???????for(int i = 1; i <= n; i++) ???????????if(sa[i] > w) tp[++p] = sa[i] - w; ???????Rsort(); ???????swap(rank, tp); ???????p = rank[sa[1]] = 1; ???????for(int i = 2; i <= n; i++) ???????????rank[sa[i]] = cmp(tp, sa[i], sa[i - 1], w) ? p : ++p; ???}}int main(){ ???scanf("%s", s + 1); ???n = strlen(s + 1); ???for(int i = 1; i <= n; i++) ???????s[i + n] = s[i]; ???n <<= 1; ???suffix(); ???n >>= 1; ???for(int i = 1; i <= (n << 1); i++) ???????if(sa[i] <= n) printf("%c", s[sa[i] + n - 1]); ???return 0;}
[JSOI2007]字符加密Cipher
原文地址:http://www.cnblogs.com/ruoruoruo/p/7440324.html