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

[JSOI2007]字符加密Cipher SA

时间:2018-01-12 19:00:47      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:line   内容   字符串   图片   方法   class   std   sam   status   

[JSOI2007]字符加密Cipher

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 7859  Solved: 3410
[Submit][Status][Discuss]

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。

 
题解:先将于2倍的然后构造后缀数组即可,
满足条件的是SA中<=n,的那些+n-1个点。
 
 1 #include<cstring>
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<iostream>
 6 
 7 #define N 200007
 8 using namespace std;
 9 inline int read()
10 {
11     int x=0,f=1;char ch=getchar();
12     while(ch<0||ch>9){if (ch==-)f=-1;ch=getchar();}
13     while(ch>=0&&ch<=9){x=(x<<3)+(x<<1)+ch-0;ch=getchar();}
14     return x*f;
15 }
16 
17 int n,k;
18 int s[N],sa[N],rk[N*2],A[N],zhi[N];
19 int a[N],b[N],cnta[N],cntb[N],tsa[N],height[N];
20 char ch[N];
21 
22 void Get_SA()
23 {
24     for (int i=1;i<=n;i++)cnta[i]=0;
25     for (int i=1;i<=n;i++)cnta[s[i]]++;
26     for (int i=1;i<=n;i++)cnta[i]+=cnta[i-1];
27     for (int i=n;i>=1;i--)sa[cnta[s[i]]--]=i;
28     rk[sa[1]]=1;
29     for (int i=2;i<=n;i++)rk[sa[i]]=rk[sa[i-1]]+(s[sa[i]]!=s[sa[i-1]]);
30     for (int i=1;rk[sa[n]]!=n;i<<=1)
31     {
32         for (int j=1;j<=n;j++)a[j]=rk[j],b[j]=rk[j+i];
33         for (int j=0;j<=n;j++)cnta[j]=cntb[j]=0;
34         for (int j=1;j<=n;j++)cnta[a[j]]++,cntb[b[j]]++;
35         for (int j=1;j<=n;j++)cnta[j]+=cnta[j-1],cntb[j]+=cntb[j-1];
36         for (int j=n;j>=1;j--)tsa[cntb[b[j]]--]=j;
37         for (int j=n;j>=1;j--)sa[cnta[a[tsa[j]]]--]=tsa[j];
38         rk[sa[1]]=1;
39         for (int j=2;j<=n;j++)
40             rk[sa[j]]=rk[sa[j-1]]+(a[sa[j]]!=a[sa[j-1]]||b[sa[j]]!=b[sa[j-1]]);
41     }
42 }
43 int main()
44 {
45     scanf("%s",ch+1);
46     int len;
47     len=n=strlen(ch+1);
48     for (int i=1;i<=n;i++)A[i]=s[i]=(int)(ch[i]);
49     sort(A+1,A+len+1);
50     len=unique(A+1,A+len+1)-A-1;
51     for (int i=1;i<=len;i++)zhi[i]=A[i];
52     for (int i=1;i<=n;i++)s[i+n]=s[i]=lower_bound(A+1,A+len+1,s[i])-A;
53     s[n+n]=0;
54     int num=n;n=2*n-1;
55     Get_SA();
56     for (int i=1;i<=n;i++)
57         if (sa[i]<=num) putchar(char(zhi[s[sa[i]+num-1]]));
58 }

 

[JSOI2007]字符加密Cipher SA

标签:line   内容   字符串   图片   方法   class   std   sam   status   

原文地址:https://www.cnblogs.com/fengzhiyuan/p/8277287.html

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