码迷,mamicode.com
首页 > Web开发 > 详细

[BZOJ 1031] [JSOI2007] 字符加密Cipher

时间:2015-06-12 22:09:52      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:

1031: [JSOI2007]字符加密Cipher

Time Limit: 10 Sec
Memory Limit: 162 MB

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。

【题解】

稍微入门了后缀数组,这是基础题。

然而NOIP并不考,我得先备战NOIP TAT

技术分享
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <algorithm>
 5 #include <cstdio>
 6 #define N 220000
 7 using namespace std;
 8 #define rep(i,a,b) for(i=a;i<b;++i)
 9 #define drep(i,a,b) for(i=a;i>=b;--i)
10 using namespace std;
11 int p[N],wc[N],wv[N],wa[N],wb[N],rank[N],sa[N];
12 char s[N];
13 inline bool cmp(int *r,int a,int b,int l) {
14     return r[a]==r[b]&&r[a+l]==r[b+l];
15 }
16 inline void tate(int *x,int *y,char *r,int n,int m,bool opt) {
17     int i;
18     rep(i,0,m) wc[i]=0;
19     rep(i,0,n) wc[opt?(x[i]=r[i]):wv[i]]++;
20     rep(i,1,m) wc[i]+=wc[i-1];
21     drep(i,n-1,0) sa[--wc[opt?x[i]:wv[i]]]=opt?i:y[i];
22 }
23 void f(char *r,int *sa,int n,int m) {
24     int i,j,p,*x=wa,*y=wb,*t;
25     tate(x,y,r,n,m,1);
26     for (j=1,p=1;p<n;j<<=1,m=p) {
27         p=0;
28         rep(i,n-j,n) y[p++]=i;
29         rep(i,0,n) if(sa[i]>=j) y[p++]=sa[i]-j;
30         rep(i,0,n) wv[i]=x[y[i]];
31         tate(x,y,r,n,m,0);
32         for (t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;++i)
33             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
34     }
35 }
36 int main() {
37     scanf("%s",s);
38     int slen=strlen(s);
39     int n=slen*2;
40     for(int i=0;i<slen;i++) s[slen+i]=s[i];
41     s[n-1]=0;
42     f(s,sa,n,300);
43     for(int i=0;i<n;i++) rank[sa[i]]=i;
44     for(int i=0;i<slen;i++) p[rank[i]]=s[i+slen-1];
45     for(int i=0;i<n;i++) if(p[i]) printf("%c",p[i]);
46     return 0;
47 }
View Code

 

[BZOJ 1031] [JSOI2007] 字符加密Cipher

标签:

原文地址:http://www.cnblogs.com/TonyNeal/p/bzoj1031.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!