[BZOJ1031][JSOI2007]字符加密Cipher 解题报告

Description

  喜欢钻研问题的JS 同学,最近又迷上了对加密方法的思考。一天,他突然想出了一种他认为是终极的加密办法:把需要加密的信息排成一圈,显然,它们有很多种不同的读法。例如下图,可以读作:

 

  JSOI07 SOI07J OI07JS I07JSO 07JSOI 7JSOI0 把它们按照字符串的大小排序: 07JSOI 7JSOI0 I07JSO JSOI07 OI07JS SOI07J 读出最后一列字符:I0O7SJ,就是加密后的字符串(其实这个加密手段实在很容易破解,鉴于这是突然想出来的,那就^^)。但是,如果想加密的字符串实在太长,你能写一个程序完成这个任务吗?

  这道题好像也做了挺久...一个半小时吧

  首先题目很亲切 总感觉去年暑假在镇中有过类似的题 但是那道题好像有神奇的O(n)做法

  其实问题可以转化为将字符串及其循环以后的n-1个串从小到大排序,然后输出字符串首位的前一位字符

  我们要解决字符串及其循环以后一共n个串的排序

  我用后缀数组解决

  我们可以直接用后缀数组处理出1 << (trunc(ln(n)/ln(2)))长度的排序

  将后缀处理成子串的方法就在原串后面再接一次

  然后再类似于倍增一点点将剩下的长度加入

  实现方法类似于后缀数组 几个细节改动一下

  但是由于要用到中间的数据,所以sa和rank数组要在每一次之后保留不能重复利用

  还是一道非常不错的题呢^

  

  1 program bzoj1031;
  2 const maxn=200010;
  3 var i,x,n:longint;
  4     ss:ansistring;
  5     a,s,tmp,rk,sa2:array[-1..maxn]of longint;
  6     rank,sa:array[-1..20,-1..maxn]of longint;
  7 
  8 function max(a,b:longint):longint;
  9 begin
 10         if a>b then exit(a) else exit(b);
 11 end;
 12 
 13 procedure Suffix_Array;
 14 var i,j,k,p,v0,v00,v01,v1,size:longint;
 15 begin
 16         size:=256;
 17     for i:=0 to n-1 do rank[0,i]:=a[i];
 18     for i:=0 to size-1 do s[i]:=0;
 19     for i:=0 to n-1 do inc(s[rank[0,i]]);
 20     for i:=1 to size-1 do inc(s[i],s[i-1]);
 21     for i:=n-1 downto 0 do
 22     begin
 23              dec(s[rank[0,i]]);
 24              sa[0,s[rank[0,i]]]:=i;
 25     end;
 26     j:=1;k:=1;
 27         size:=n;
 28         while j<=n >> 1 do
 29     begin
 30         p:=0;
 31         for i:=n-j to n-1 do
 32         begin
 33             tmp[p]:=i;
 34             inc(p);
 35         end;
 36         for i:=0 to n-1 do if sa[k-1,i]-j>=0 then
 37         begin
 38             tmp[p]:=sa[k-1,i]-j;
 39             inc(p);
 40         end;
 41         for i:=0 to size-1 do s[i]:=0;
 42         for i:=0 to n-1 do inc(s[rank[k-1,i]]);
 43         for i:=1 to size-1 do inc(s[i],s[i-1]);
 44         for i:=n-1 downto 0 do
 45         begin
 46             dec(s[rank[k-1,tmp[i]]]);
 47             sa[k,s[rank[k-1,tmp[i]]]]:=tmp[i];
 48         end;
 49         p:=0;rank[k,sa[k,0]]:=0;
 50         for i:=1 to n-1 do
 51         begin
 52             v0:=sa[k,i-1];v1:=sa[k,i];
 53             if v0+j<n then v00:=rank[k-1,v0+j] else v00:=-1;
 54             if v1+j<n then v01:=rank[k-1,v1+j] else v01:=-1;
 55             if (rank[k-1,v0]=rank[k-1,v1])and(v00=v01) then rank[k,sa[k,i]]:=p else
 56             begin
 57                 inc(p);
 58                 rank[k,sa[k,i]]:=p;
 59 
 60             end;
 61         end;
 62         j:=j << 1;inc(k);
 63         end;
 64 end;
 65 
 66 procedure solve;
 67 var i,j,k,p,x,rec,v0,v1,v00,v01,size:longint;
 68 begin
 69     x:=trunc(ln(n >> 1)/ln(2));
 70         size:=max(256,n);
 71     for i:=0 to n-1 do rk[i]:=rank[x,i];
 72     for i:=0 to size-1 do s[i]:=0;
 73     for i:=0 to n-1 do inc(s[rk[i]]);
 74     for i:=1 to size-1 do inc(s[i],s[i-1]);
 75     for i:=n-1 downto 0 do
 76     begin
 77         dec(s[rk[i]]);
 78         sa2[s[rk[i]]]:=i;
 79     end;
 80     rec:=n >> 1-1 << x;
 81     while rec<>0 do
 82     begin
 83         x:=trunc(ln(rec)/ln(2));
 84         p:=0;
 85         for i:=n-1 << x to n-1 do
 86         begin
 87             tmp[p]:=i;
 88             inc(p);
 89         end;
 90         for i:=0 to n-1 do if sa[x,i]-1 << x>=0 then
 91         begin
 92             tmp[p]:=sa[x,i]-1 << x;
 93             inc(p);
 94         end;
 95         for i:=0 to size-1 do s[i]:=0;
 96         for i:=0 to n-1 do inc(s[rk[i]]);
 97         for i:=1 to size-1 do inc(s[i],s[i-1]);
 98         for i:=0 to n-1 do
 99         begin
100             dec(s[rk[tmp[i]]]);
101             sa2[s[rk[tmp[i]]]]:=tmp[i];
102         end;
103         p:=0;tmp[sa2[0]]:=0;
104         for i:=1 to n-1 do
105         begin
106             v0:=sa2[i-1];v1:=sa2[i];
107             if v0+1 << x<n then v00:=rank[x,v0+1 << x] else v00:=-1;
108             if v1+1 << x<n then v01:=rank[x,v1+1 << x] else v01:=-1;
109             if (rk[v0]=rk[v1])and(v00=v01) then tmp[sa2[i]]:=p else
110             begin
111                 inc(p);
112                 tmp[sa2[i]]:=p;
113             end;
114         end;
115         for i:=0 to n-1 do rk[i]:=tmp[i];
116         dec(rec,1 << x);
117     end;
118 end;
119 
120 begin
121     readln(ss);n:=length(ss);
122     for i:=0 to n-1 do a[i]:=ord(ss[i+1]);
123         for i:=n to 2*n-1 do a[i]:=a[i-n];
124         n:=n*2;
125     Suffix_Array;
126         solve;
127     for i:=0 to n-1 do if sa2[i]<(n >> 1) then
128     begin
129         x:=sa2[i]-1;
130         if x=-1 then x:=n >> 1-1;              
131             write(ss[x+1]);
132     end;
133 end.

 

 

 

posted @ 2015-04-10 10:37  mjy0724  阅读(188)  评论(0编辑  收藏  举报