bzoj 1031[JSOI2007]字符加密 - 后缀数组
1031: [JSOI2007]字符加密Cipher
Time Limit: 10 Sec Memory Limit: 162 MBDescription
喜欢钻研问题的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。
应该是一道板子题吧
把字符串复制一遍搁到后边就行了
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 #define LL long long 6 using namespace std; 7 8 const int MAXN = 3e5 + 10; 9 char str[MAXN]; 10 int m; 11 int ra[MAXN], tp[MAXN]; 12 int SA[MAXN]; 13 int cur[MAXN]; 14 int c[MAXN]; 15 int len; 16 int p; 17 inline LL read() 18 { 19 LL x = 0, w = 1; char ch = 0; 20 while(ch < '0' || ch > '9') { 21 if(ch == '-') { 22 w = -1; 23 } 24 ch = getchar(); 25 } 26 while(ch >= '0' && ch <= '9') { 27 x = x * 10 + ch - '0'; 28 ch = getchar(); 29 } 30 return x * w; 31 } 32 33 void sort(int m) 34 { 35 for(int i = 0; i <= m; i++) { 36 c[i] = 0; 37 } 38 for(int i = 1; i <= len; i++) { 39 c[ra[tp[i]]]++; 40 } 41 for(int i = 1; i <= m; i++) { 42 c[i] += c[i - 1]; 43 } 44 for(int i = len; i >= 1; i--) { 45 SA[c[ra[tp[i]]]--] = tp[i]; 46 } 47 } 48 49 void copy() 50 { 51 for(int i = 1; i <= len; i++) { 52 cur[i] = ra[i]; 53 } 54 } 55 56 void suffix() 57 { 58 for(int i = 1; i <= len; i++) { 59 ra[i] = str[i]; 60 tp[i] = i; 61 } 62 sort(m = 128); 63 for(int w = 1, p = 0; p < len; w += w, m = p) { 64 p = 0; 65 for(int j = len - w + 1; j <= len; j++) { 66 tp[++p] = j; 67 } 68 for(int i = 1; i <= len; i++) { 69 if(SA[i] > w) { 70 tp[++p] = SA[i] - w; 71 } 72 } 73 sort(m); 74 copy(); 75 ra[SA[1]] = p = 1; 76 for(int i = 2; i <= len; i++) { 77 if(cur[SA[i]] == cur[SA[i - 1]] && cur[SA[i - 1] + w] == cur[SA[i] + w]) { 78 ra[SA[i]] = p; 79 } else { 80 ra[SA[i]] = ++p; 81 } 82 } 83 } 84 } 85 int main() 86 { 87 scanf("%s", str + 1); 88 len = strlen(str + 1); 89 for(int i = 1; i <= len; i++) { 90 str[i + len] = str[i]; 91 } 92 len += len; 93 suffix(); 94 for(int i = 1; i <= len; i++) { 95 if(SA[i] <= len / 2) 96 cout<<str[SA[i] + len / 2 - 1]; 97 } 98 cout<<endl; 99 return 0; 100 }