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.

 

你可能感兴趣的:(2007)