BZOJ 1031 字符加密

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1031

1031: [JSOI2007]字符加密Cipher

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 6983  Solved: 3003
[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。

 
 
分析:(卿学姐)
题目很容易想到是后缀数组做,可以排序后缀嘛,怎么构造这个问题的解呢?
只要扩充一半字符串,
每个后缀对应了一个排列,但是1和7结果是相同的,只要算一次就好了;
 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 1000000 + 5;
 6 
 7 char s[2*maxn];
 8 int n;
 9 int sa[maxn],ra[maxn],tmp[maxn],height[maxn];
10 int c[maxn];
11 
12 void build_sa()
13 {
14     int m = 128;
15     int* x = ra,*y=tmp;
16 
17     for(int i=0;i<m;i++) c[i] = 0;
18     for(int i=0;i<n;i++) c[x[i]=s[i]]++;
19     for(int i=1;i<m;i++) c[i] +=c[i-1];
20     for(int i=n-1;i>=0;i--) sa[--c[x[i]]] = i;
21 
22     for(int k=1;k<=n;k<<=1) {
23         int p = 0;
24 
25         for(int i=n-k;i<n;i++) y[p++] = i;
26         for(int i=0;i<n;i++) if(sa[i]>=k) y[p++] = sa[i]-k;
27 
28         for(int i=0;i<m;i++) c[i] = 0;
29         for(int i=0;i<n;i++) c[x[y[i]]]++;
30         for(int i=0;i<m;i++) c[i]+=c[i-1];
31         for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]] = y[i];
32 
33         swap(x,y);
34         p = 1;x[sa[0]] = 0;
35 
36         for(int i=1;i<n;i++)
37             x[sa[i]] = (y[sa[i-1]]==y[sa[i]])&&y[sa[i-1]+k]==y[sa[i]+k] ? p-1:p++;
38         if(p>=n) break;
39         m = p;
40     }
41 }
42 
43 int main()
44 {
45     scanf("%s",s);
46     int len = strlen(s);
47 
48     for(int i=len;i<2*len;i++)
49         s[i] = s[i-len];
50     n = 2*len;
51     build_sa();
52     for(int i=1;i<n;i++) {
53         if(sa[i]<len)
54             putchar(s[sa[i]+len-1]);
55     }
56     puts("");
57 
58     return 0;
59 }
View Code

 

 
posted @ 2017-05-08 21:28  小草的大树梦  阅读(261)  评论(0编辑  收藏  举报