真正的危机不是机器人像人一样思考,而是人像机器一样思考。 ——凉宫春日的忧郁

[JSOI2007]字符加密Cipher

[JSOI2007]字符加密Cipher

题目

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

 

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

INPUT

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

OUTPUT

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

SAMPLE

INPUT

JSOI07

OUTPUT

I0O7SJ

解题报告

第一道不是板子题的$SA$(这tm不是板子题?)

首先,因为这玩意是个环,所以我们把串翻倍

然后跑一遍板子,求出$SA$

接下来就是怎么用的问题了

我们知道,$SA[i]$表示第$i$个后缀的首位置下标,所以我们可以找到对应每个排名的下标,对应输出相应字符即可

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 char ch[100005],s[200010];
 6 int len;
 7 int n,m;
 8 int t1[200010],t2[200010],t3[200010],buc[200010];
 9 int sa[200010],rank[200010];
10 inline void Suffix(){
11     int i,j,k(0),p(0),*x(t1),*y(t2),*t;
12     for(i=0;i<=m;++i)buc[i]=0;
13     for(i=1;i<=n;++i)++buc[x[i]=s[i]];
14     for(i=1;i<=m;++i)buc[i]+=buc[i-1];
15     for(i=n;i>=1;--i)sa[buc[x[i]]--]=i;
16     for(j=1;p<n;j<<=1,m=p){
17         for(p=0,i=n-j+1;i<=n;++i)y[++p]=i;
18         for(i=1;i<=n;++i)
19             if(sa[i]-j>0)
20                 y[++p]=sa[i]-j;
21         for(i=0;i<=m;++i)buc[i]=0;
22         for(i=1;i<=n;++i)t3[i]=x[y[i]];
23         for(i=1;i<=n;++i)++buc[t3[i]];
24         for(i=1;i<=m;++i)buc[i]+=buc[i-1];
25         for(i=n;i>=1;--i)sa[buc[t3[i]]--]=y[i];
26         for(t=x,x=y,y=t,p=1,x[sa[1]]=1,i=2;i<=n;++i)
27             x[sa[i]]=((y[sa[i]]==y[sa[i-1]])&&(y[sa[i]+j]==y[sa[i-1]+j]))?p:++p;
28     }
29     for(i=1;i<=n;++i)rank[sa[i]]=i;
30 }
31 inline char get(int x){
32     int tmp(sa[x]);//cout<<x<<" "<<tmp<<endl;
33     tmp=tmp+len-1;
34     if(tmp>n)
35         tmp-=len;
36     return s[tmp];
37 }
38 int main(){
39     scanf("%s",ch);
40     len=strlen(ch);
41     for(int i=1;i<=len;++i)
42         s[i]=ch[i-1];
43     for(int i=1;i<=len;++i)
44         s[len+i]=ch[i-1];
45     n=len<<1;
46     m=130;
47     Suffix();
48     for(int i=2;i<=n;i+=2)
49         putchar(get(i));
50 }
View Code

 

posted @ 2017-09-21 20:45  Hzoi_Mafia  阅读(179)  评论(0编辑  收藏  举报
我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。 ——死神