HYSBZ - 1031 字符加密Cipher
阿新 • • 發佈:2017-10-25
tchar putchar n) std 輸入 tin 一個 -- [0
喜歡鉆研問題的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。
做法:
後綴數組模板題,把字符串按自己本身擴充一次,求後綴數組即可。
代碼:
#include <bits/stdc++.h> using namespace std; const int MAXN = 1050010; #define F(x) ((x)/3+((x)%3==1?0:tb)) #define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2) int wa[MAXN*3],wb[MAXN*3],wv[MAXN*3],wss[MAXN*3]; int c0(int *r,int a,int b) { return r[a] == r[b] && r[a+1] == r[b+1] && r[a+2] == r[b+2]; } int c12(int k,int *r,int a,int b) { if(k == 2) return r[a] < r[b] || ( r[a] == r[b] && c12(1,r,a+1,b+1) ); else return r[a] < r[b] || ( r[a] == r[b] && wv[a+1] < wv[b+1] ); } void sort(int *r,int *a,int *b,int n,int m) { int i; for(i = 0;i < n;i++)wv[i] = r[a[i]]; for(i = 0;i < m;i++)wss[i] = 0; for(i = 0;i < n;i++)wss[wv[i]]++; for(i = 1;i < m;i++)wss[i] += wss[i-1]; for(i = n-1;i >= 0;i--) b[--wss[wv[i]]] = a[i]; } void dc3(int *r,int *sa,int n,int m) { int i, j, *rn = r + n; int *san = sa + n, ta = 0, tb = (n+1)/3, tbc = 0, p; r[n] = r[n+1] = 0; for(i = 0;i < n;i++)if(i %3 != 0)wa[tbc++] = i; sort(r + 2, wa, wb, tbc, m); sort(r + 1, wb, wa, tbc, m); sort(r, wa, wb, tbc, m); for(p = 1, rn[F(wb[0])] = 0, i = 1;i < tbc;i++) rn[F(wb[i])] = c0(r, wb[i-1], wb[i]) ? p - 1 : p++; if(p < tbc)dc3(rn,san,tbc,p); else for(i = 0;i < tbc;i++)san[rn[i]] = i; for(i = 0;i < tbc;i++) if(san[i] < tb)wb[ta++] = san[i] * 3; if(n % 3 == 1)wb[ta++] = n - 1; sort(r, wb, wa, ta, m); for(i = 0;i < tbc;i++)wv[wb[i] = G(san[i])] = i; for(i = 0, j = 0, p = 0;i < ta && j < tbc;p++) sa[p] = c12(wb[j] % 3, r, wa[i], wb[j]) ? wa[i++] : wb[j++]; for(;i < ta;p++)sa[p] = wa[i++]; for(;j < tbc;p++)sa[p] = wb[j++]; } char s[MAXN]; int a[MAXN]; int sa[MAXN]; int main() { while(gets(s)!=NULL) { int n=strlen(s); for (int i=n;i<2*n;i++) s[i]=s[i-n]; for (int i=0;i<2*n;i++) a[i]=s[i]; a[2*n]=0; dc3(a,sa,2*n+1,300); int num=0; for (int i=1;i<=2*n;i++){ int p; // cout<<s+sa[i]<<endl;continue; if (2*n-sa[i]<n||sa[i]>=n) continue; num++; p=sa[i]+n-1; putchar(s[p]); if(num>=n) break; } } return 0; }
HYSBZ - 1031 字符加密Cipher