[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.
时间: 2024-07-30 10:31:44

[BZOJ1031][JSOI2007]字符加密Cipher 解题报告的相关文章

[BZOJ1031] [JSOI2007] 字符加密Cipher (后缀数组)

Description 喜欢钻研问题的JS同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法 :把需要加密的信息排成一圈,显然,它们有很多种不同的读法.例如下图,可以读作: JSOI07 SOI07J OI07JS I07JSO 07JSOI 7JSOI0把它们按照字符串的大小排序:07JSOI 7JSOI0 I07JSO JSOI07 OI07JS SOI07J读出最后一列字符:I0O7SJ,就是加密后的字符串(其实这个加密手段实在很容易破解,鉴于这是 突然想出来

[bzoj1031][JSOI2007]字符加密Cipher

显然把原串复制一遍,然后排序长度为len的各个后缀就行了. 我只是突然想试试hash...代码量不到1k而且似乎竟然比写得不是很好的后缀数组快?自然溢出大法好... 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define ui unsigned int 6 using namespace std; 7 const int maxn=

[BZOJ1031][JSOI2007]字符加密Cipher(后缀数组)

传送门 算是个模板. 题目说循环,那就再复制一串拼接上. 然后求后缀数组,再搞就可以. 虽然是求后缀,会在后面多一些字符串,然而题目中说的是循环一圈,但是没有影响. ——代码 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define N 200005 5 6 int m = 'z' + 1; 7 int len, buc[N], x[N], y[N], sa[N]; 8 char s

BZOJ 1031: [JSOI2007]字符加密Cipher 后缀数组

1031: [JSOI2007]字符加密Cipher Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 6014  Solved: 2503[Submit][Status][Discuss] Description 喜欢钻研问题的JS同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法 :把需要加密的信息排成一圈,显然,它们有很多种不同的读法.例如下图,可以读作: JSOI07 SOI07J OI07JS I07JSO 0

bzoj1031[JSOI2007]字符加密

bzoj1031[JSOI2007]字符加密 题意: 一种加密办法是把需要加密的信息排成一圈,显然,它们有很多种不同的读法.把它们按照字符串的大小排序,读出最后一列字符,就是加密后的字符串.给出原字符串,求加密后的字符串. 题解: 将原字符串重复后接在后面,然后求后缀数组,注意求完后要取那些长度大于原字符串长度a2的后缀的第a2个字符. 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm>

【BZOJ-1031】字符加密Cipher 后缀数组

1031: [JSOI2007]字符加密Cipher Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 5504  Solved: 2277[Submit][Status][Discuss] Description 喜欢钻研问题的JS同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法 :把需要加密的信息排成一圈,显然,它们有很多种不同的读法.例如下图,可以读作: JSOI07 SOI07J OI07JS I07JSO 0

[JSOI2007]字符加密Cipher

1031: [JSOI2007]字符加密Cipher Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 7384  Solved: 3198 [Submit][Status][Discuss] Description 喜欢钻研问题的JS同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法 :把需要加密的信息排成一圈,显然,它们有很多种不同的读法.例如下图,可以读作: JSOI07 SOI07J OI07JS I07JSO

bzoj 1031: [JSOI2007]字符加密Cipher 後綴數組模板題

1031: [JSOI2007]字符加密Cipher Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3157  Solved: 1233[Submit][Status] Description 喜欢钻研问题的JS 同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法:把需要加密的信息排成一圈,显然,它们有很多种不同的读法.例如下图,可以读作: JSOI07 SOI07J OI07JS I07JSO 07JSOI 7JS

BZOJ 题目1031: [JSOI2007]字符加密Cipher(后缀数组sa简单应用)

1031: [JSOI2007]字符加密Cipher Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4318  Solved: 1760 [Submit][Status][Discuss] Description 喜欢钻研问题的JS 同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法:把需要加密的信息排成一圈,显然,它们有很多种不同的读法.例如下图,可以读作: JSOI07 SOI07J OI07JS I07JSO