標籤:space pop UI cst namespace split limit time 程式
1031: [JSOI2007]字元加密Cipher
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 4175 Solved: 1694
[Submit][Status][Discuss]
Description
喜歡鑽研問題的JS 同學,近期又迷上了對加密方法的思考。一天,他突然想出了一種他覺得是終極的加密辦法:把須要加密的資訊排成一圈,顯然,它們有非常多種不同的讀法。比例如以,能夠讀作:
JSOI07 SOI07J OI07JS I07JSO 07JSOI 7JSOI0 把它們依照字串的大小排序: 07JSOI 7JSOI0 I07JSO JSOI07 OI07JS SOI07J 讀出最後一列字元:I0O7SJ,就是加密後的字串(事實上這個加密手段實在非常easy破解,鑒於這是突然想出來的。那就^^)。可是。假設想加密的字串實在太長,你能寫一個程式完畢這個任務嗎?
Input
輸入檔案包括一行。欲加密的字串。注意字串的內容不一定是字母、數字,也能夠是符號等。
Output
輸出一行。為加密後的字串。
Sample Input
JSOI07
Sample Output
I0O7SJ
HINT
對於100%的資料字串的長度不超過100000。
思路:尾碼數組的模板題。
我們僅僅須要先將這個串拷貝到後面,然後處理處sa,依次輸出排名中的起點
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N n*2-1const int M=200100;char ch[M];int n,m=0,sa[M],t1[M],t2[M],c[M];void build_sa(){ int i,p,k,*x=t1,*y=t2; for(i=0;i<m;++i) c[i]=0; for(i=0;i<N;++i) c[x[i]=ch[i]]++; for(i=1;i<m;++i) c[i]+=c[i-1]; for(i=N-1;i>=0;--i) sa[--c[x[i]]]=i; for(k=1;k<=N;k<<=1){ p=0; for(i=N-k;i<N;++i) y[p++]=i; for(i=0;i<N;++i) if(sa[i]>=k) y[p++]=sa[i]-k; for(i=0;i<m;++i) c[i]=0; for(i=0;i<N;++i) c[x[y[i]]]++; for(i=0;i<m;++i) c[i]+=c[i-1]; for(i=N-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(i=1;i<N;++i) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; if(p>=N) break; m=p; }}int main(){ int i,j; scanf("%s",&ch); n=strlen(ch); for(i=0;i<n-1;++i) ch[i+n]=ch[i]; for(i=0;i<n;++i) m=max(m,(int)ch[i]); m+=1; build_sa(); for(i=0;i<N;++i) if(sa[i]<n) printf("%c",ch[sa[i]+n-1]);}
[bzoj1031][JSOI2007]字元加密Cipher