[JSOI2007]字符加密Cipher

[JSOI2007]字符加密Cipher

Time Limit:10000MS Memory Limit:165536K
Total Submit:76 Accepted:34
Case Time Limit:1000MS

Description

喜欢钻研问题的JS 同学,最近又迷上了对加密方法的思考。一天,他突然想出了一种他认为是终极的加密办法:把需要加密的信息排成一圈,显然,它们有很多种不同的读法。例如下图,可以读作:

JSOI07
SOI07J
OI07JS
I07JSO
07JSOI
7JSOI0
把它们按照字符串的大小排序:
07JSOI
7JSOI0
I07JSO
JSOI07
OI07JS
SOI07J
读出最后一列字符:I0O7SJ,就是加密后的字符串(其实这个加密手段实在很容易破解,鉴于这是突然想出来的,那就^^)。
但是,如果想加密的字符串实在太长,你能写一个程序完成这个任务吗?

Input

输入文件包含一行,欲加密的字符串。注意字符串的内容不一定是字母、数字,也可以是符号等。

Output

输出一行,为加密后的字符串。

Sample Input

Sample Output

Source
很显然,暴力上后缀数组。。。哎。原来觉得后缀数组很难,现在随便写了,看来事在人为啊囧。。
Code:

#include<cstdio>#include<algorithm>#include<iostream>#define rep(i,n) for(int i=0;i<n;i++)using namespace std;const int maxn=100000*2+1;int n,m,sa[maxn],ta[maxn],tb[maxn],*x=ta,*y=tb;char C[maxn];bool cmp(int i,int j,int l){ return y[i]==y[j]&&y[i+l]==y[j+l];}void Sort(){ static int w[maxn]; rep(i,m)w[i]=0;rep(i,n)w[x[y[i]]]++; rep(i,m-1)w[i+1]+=w[i]; for(int i=n-1;i>=0;i–)sa[–w[x[y[i]]]]=y[i];}void Da(){ int i,j,p; rep(i,n)x[i]=C[i],y[i]=i;Sort(); for(p=1,j=1;p<n;m=p,j*=2) { for(p=0,i=n-j;i<n;i++)y[p++]=i; rep(i,n)if(sa[i]>=j)y[p++]=sa[i]-j;Sort(); for(swap(x,y),i=1,p=1,x[sa[0]]=0;i<n;i++) x[sa[i]]=cmp(sa[i-1],sa[i],j)?p-1:p++; }}int main(){ //freopen("in","r",stdin); gets(C);n=strlen(C); rep(i,n)C[n+i]=C[i];n<<=1;C[n++]=0;m=256; Da();int s=n/2; rep(i,n)if(sa[i]<s)printf("%c",C[s+sa[i]-1]); printf("n");}I0O7SJ数据规模对于40%的数据字符串的长度不超过10000。对于100%的数据字符串的长度不超过100000。JSOI07

One thought on “[JSOI2007]字符加密Cipher

Leave a Reply

Your email address will not be published. Required fields are marked *