zoukankan      html  css  js  c++  java
  • [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.
  • 相关阅读:
    java方法名的重载
    数据库ifnull方法
    java类的方法
    java属性的默认值
    sublime使用攻略
    1046 Shortest Distance
    1047 Student List for Course
    1048 Find Coins
    1049 Counting Ones
    1050 String Subtraction
  • 原文地址:https://www.cnblogs.com/mjy0724/p/4413891.html
Copyright © 2011-2022 走看看