除草向、
裸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.