Description
喜欢钻研问题的JS 同学,最近又迷上了对加密方法的思考。一天,他突然想出了一种他认为是终极的加密办法:把需要加密的信息排成一圈,显然,它们有很多种不同的读法。例如下图,可以读作: JSOI07 SOI07J OI07JS I07JSO 07JSOI 7JSOI0 把它们按照字符串的大小排序: 07JSOI 7JSOI0 I07JSO JSOI07 OI07JS SOI07J 读出最后一列字符:I0O7SJ,就是加密后的字符串(其实这个加密手段实在很容易破解,鉴于这是突然想出来的,那就^^)。但是,如果想加密的字符串实在太长,你能写一个程序完成这个任务吗?
Input
输入文件包含一行,欲加密的字符串。注意字符串的内容不一定是字母、数字,也可以是符号等。
Output
输出一行,为加密后的字符串。
Sample Input
JSOI07
Sample Output
I0O7SJ
数据规模
对于40%的数据字符串的长度不超过10000。
对于100%的数据字符串的长度不超过100000。
裸的后缀数组,一开始想的是后缀自动机(囧,建好自动机后按字典序dfs遍历长度为len的,直接超时和爆内存)
1 const 2 maxn=200010; 3 var 4 sa,x,y,c:array[0..maxn]of longint; 5 s:ansistring; 6 n:longint; 7 8 procedure init; 9 var 10 i,k:longint; 11 begin 12 readln(s); 13 s:=s+s; 14 n:=length(s); 15 for i:=1 to n do 16 begin 17 y[i]:=ord(s[i]); 18 x[i]:=y[i]; 19 end; 20 for i:=1 to n do 21 inc(c[y[i]]); 22 for i:=2 to 128 do 23 inc(c[i],c[i-1]); 24 for i:=1 to n do 25 begin 26 sa[c[y[i]]]:=i; 27 dec(c[y[i]]); 28 end; 29 x[sa[1]]:=1; 30 k:=1; 31 for i:=2 to n do 32 begin 33 if y[sa[i]]<>y[sa[i-1]] then inc(k); 34 x[sa[i]]:=k; 35 end; 36 end; 37 38 procedure work; 39 var 40 p,i,k:longint; 41 begin 42 p:=1; 43 while p<n do 44 begin 45 for i:=1 to n-p do 46 y[i]:=x[i+p]; 47 for i:=n-p+1 to n do 48 y[i]:=0; 49 for i:=0 to n do 50 c[i]:=0; 51 for i:=1 to n do 52 inc(c[y[i]]); 53 for i:=1 to n do 54 inc(c[i],c[i-1]); 55 for i:=1 to n do 56 begin 57 sa[c[y[i]]]:=i; 58 dec(c[y[i]]); 59 end; 60 for i:=0 to n do 61 c[i]:=0; 62 for i:=1 to n do 63 inc(c[x[i]]); 64 for i:=1 to n do 65 inc(c[i],c[i-1]); 66 for i:=n downto 1 do 67 begin 68 y[sa[i]]:=c[x[sa[i]]]; 69 dec(c[x[sa[i]]]); 70 end; 71 for i:=1 to n do 72 sa[y[i]]:=i; 73 y[sa[1]]:=1; 74 k:=1; 75 for i:=2 to n do 76 begin 77 if (x[sa[i]]<>x[sa[i-1]]) or (x[sa[i]+p]<>x[sa[i-1]+p]) then inc(k); 78 y[sa[i]]:=k; 79 end; 80 x:=y; 81 p:=p<<1; 82 end; 83 for i:=1 to n do 84 sa[x[i]]:=i; 85 for i:=1 to n do 86 if sa[i]<=n>>1 then write(s[sa[i]+n>>1-1]); 87 end; 88 89 begin 90 init; 91 work; 92 end.