BZOJ1031: [JSOI2007]字符加密Cipher - 后缀数组 -
1031: [JSOI2007]字符加密Cipher
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。
Solution
倍长一下,SA直接搞。
只求sa就可以了,顺手敲了rank和height……
Code
1 #include<map> 2 #include<set> 3 #include<cmath> 4 #include<ctime> 5 #include<deque> 6 #include<queue> 7 #include<stack> 8 #include<cstdio> 9 #include<vector> 10 #include<climits> 11 #include<cstring> 12 #include<cstdlib> 13 #include<iostream> 14 #include<algorithm> 15 using namespace std; 16 typedef long long LL; 17 const int Maxn=1000000+1; 18 struct Suffix_Array 19 { 20 int c[Maxn]; 21 int sa[Maxn]; 22 void Sort(int *x,int *y,int n,int m) 23 { 24 for(int i=0;i<=m;i++)c[i]=0; 25 for(int i=1;i<=n;i++)c[x[y[i]]]++; 26 for(int i=1;i<=m;i++)c[i]+=c[i-1]; 27 for(int i=n;i>=1;i--)sa[c[x[y[i]]]--]=y[i]; 28 } 29 bool Same(int *s,int x,int y,int l) 30 { 31 return s[x]==s[y]&&s[x+l]==s[y+l]; 32 } 33 int t1[Maxn]; 34 int t2[Maxn]; 35 int rank[Maxn]; 36 int height[Maxn]; 37 void Init(int n) 38 { 39 for(int i=1;i<=n;i++)sa[i]=0; 40 } 41 void Build(int *s,int n,int m) 42 { 43 Init(n); 44 int *x=t1; 45 int *y=t2; 46 for(int i=1;i<=n;i++)x[i]=i; 47 Sort(s,x,n,m); 48 for(int i=1;i<=n;i++)x[i]=s[i]; 49 for(int j=1;j<=n;j<<=1) 50 { 51 int p=0; 52 for(int i=n-j+1;i<=n;i++)y[++p]=i; 53 for(int i=1;i<=n;i++) 54 if(j<sa[i])y[++p]=sa[i]-j; 55 Sort(x,y,n,m); 56 swap(x,y); 57 int k=0; 58 x[sa[1]]=++k; 59 for(int i=2;i<=n;i++) 60 { 61 if(!Same(y,sa[i-1],sa[i],j))k++; 62 x[sa[i]]=k; 63 } 64 m=k; 65 } 66 for(int i=1;i<=n;i++)rank[sa[i]]=i; 67 int h=0; 68 height[1]=0; 69 for(int i=1;i<=n;i++) 70 { 71 if(h!=0)h--; 72 if(rank[i]==1)continue; 73 int j=sa[rank[i]-1]; 74 while(s[i+h]==s[j+h])h++; 75 height[rank[i]]=h; 76 } 77 } 78 }suf; 79 int a[Maxn]; 80 char str[Maxn]; 81 int main() 82 { 83 // freopen("a.in","r",stdin); 84 // freopen("a.out","w",stdout); 85 gets(str+1); 86 int len=strlen(str+1); 87 int n=len*2; 88 for(int i=1;i<=len;i++)a[i]=str[i]; 89 for(int i=len+1;i<=n;i++)a[i]=str[i-len]; 90 suf.Build(a,n,130); 91 int p=1; 92 for(int i=1;i<=len;i++) 93 { 94 while(len<suf.sa[p])p++; 95 printf("%c",a[suf.sa[p]+len-1]); 96 p++; 97 } 98 printf("\n"); 99 return 0; 100 }