首页 > 代码库 > 大视野 1031 字符加密Cipher(后缀数组)
大视野 1031 字符加密Cipher(后缀数组)
字符加密Cipher
Description
喜欢钻研问题的JS 同学,最近又迷上了对加密方法的思考。一天,他突然想出了一种他认为是终极的加密办法:把需要加密的信息排成一圈,显然,它们有很多种不同的读法。例如下图,可以读作:
JSOI07 SOI07J OI07JS I07JSO 07JSOI 7JSOI0 把它们按照字符串的大小排序: 07JSOI 7JSOI0 I07JSO JSOI07 OI07JS SOI07J 读出最后一列字符:I0O7SJ,就是加密后的字符串(其实这个加密手段实在很容易破解,鉴于这是突然想出来的,那就^^)。但是,如果想加密的字符串实在太长,你能写一个程序完成这个任务吗?
Input
输入文件包含一行,欲加密的字符串。注意字符串的内容不一定是字母、数字,也可以是符号等。
Output
输出一行,为加密后的字符串。
Sample Input
JSOI07
Sample Output
I0O7SJ
一开始用string数组排序做的,果断超内存了。
分析一下给到的串:
07JSOI——>07+……+I
7JSOI0——>7+……+0
I07JSO——>I07+……+O
JSOI07——>JSOI07+(7)
OI07JS——>OI07+……+S
SOI07J——>SOI07+J
可以发现07,7,I07,JSOI07,OI07,SOI07就是原字符串的所有后缀,所以在排序时,我们只需对这些后缀排序即可。这样就要用到后缀数组。
注意:由于是环状,因此需要先复制倍增字符串,得到新串后,给新串前半部分排个序,再依次输出各自在倍增后字符串中的末尾位置即可。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 200010; char str[N]; int *rank, sa[N]; int wa[N], wb[N], wm[N]; bool comp(int *r, int a, int b, int l) { return r[a] == r[b] && r[a+l] == r[b+l]; } void get_sa(char *r, int *sa, int n, int m) { int *x = wa, *y = wb, *t, i, j, p; for(i = 0; i < m; ++i) wm[i] = 0; for(i = 0; i < n; ++i) wm[x[i] = r[i]]++; for(i = 1; i < m; ++i) wm[i] += wm[i-1]; for(i = n-1; i >= 0; --i) sa[--wm[x[i]]] = i; for(i = 0, j = 1, p = 0; p < n; j <<= 1, m = p) { for(p = 0, i = n - j; i < n; ++i) y[p++] = i; for(i = 0; i < n; ++i) if(sa[i] >= j) y[p++] = sa[i] - j; for(i = 0; i < m; ++i) wm[i] = 0; for(i = 0; i < n; ++i) wm[x[y[i]]]++; for(i = 1; i < m; ++i) wm[i] += wm[i-1]; for(i = n-1; i >= 0; --i) sa[--wm[x[y[i]]]] = y[i]; for(t = x, x = y, y = t, i = p = 1, x[sa[0]] = 0; i < n; ++i) { x[sa[i]] = comp(y, sa[i], sa[i-1], j) ? p-1 : p++; } } rank = x; } int main() { while(gets(str) != NULL) { int len = strlen(str); for(int i = 0; i < len; i++) str[i + len] = str[i]; str[2 * len] = 0; get_sa(str, sa, len * 2 + 1, 256); for(int i = 0; i <= 2 * len; i++) if(sa[i] < len) printf("%c", str[sa[i] + len - 1]); printf("\n"); } return 0; }
大视野 1031 字符加密Cipher(后缀数组)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。