1. 程式人生 > >[JSOI2007]字符加密Cipher SA

[JSOI2007]字符加密Cipher SA

time urn mst while center des names 出了 字符

[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