BZOJ1031 JSOI2007 字符加密
除草向、
裸SA、处理环的话就复制一遍挂在后面就好了、
Code:
const maxm=400001; var ch:char; s,trk,rank,sa,tsa,sum:array [0..500001] of longint; len,i,j,p,got:longint; begin {assign(input,'cipher.in'); assign(output,'cipher.out'); reset(input); rewrite(output); } len:=0; while not eoln do begin read(ch); inc(len); s[len]:=ord(ch); end; for i:=1 to len do s[i+len]:=s[i]; len:=len shl 1; for i:=1 to len do begin trk[i]:=s[i]; inc(sum[trk[i]]); end; for i:=1 to maxm do inc(sum[i],sum[i-1]); for i:=len downto 1 do begin sa[sum[trk[i]]]:=i; dec(sum[trk[i]]); end; rank[sa[1]]:=1;p:=1; for i:=2 to len do begin if trk[sa[i]]<>trk[sa[i-1]] then inc(p); rank[sa[i]]:=p; end; got:=p;j:=1; while got<len do begin fillchar(sum,sizeof(sum),0); move(rank,trk,sizeof(rank)); p:=0; for i:=len-j+1 to len do begin inc(p); tsa[p]:=i; end; for i:=1 to len do if sa[i]>j then begin inc(p); tsa[p]:=sa[i]-j; end; for i:=1 to len do begin rank[i]:=trk[tsa[i]]; inc(sum[rank[i]]); end; for i:=1 to maxm do inc(sum[i],sum[i-1]); for i:=len downto 1 do begin sa[sum[rank[i]]]:=tsa[i]; dec(sum[rank[i]]); end; rank[sa[1]]:=1;p:=1; for i:=2 to len do begin if (trk[sa[i]]<>trk[sa[i-1]]) or (trk[sa[i]+j]<>trk[sa[i-1]+j]) then inc(p); rank[sa[i]]:=p; end; got:=p;j:=j*2; end; s[0]:=s[len]; for i:=1 to len do if sa[i]<=len div 2 then write(chr(s[sa[i]-1])); writeln; {close(input); close(output);} end.