码迷,mamicode.com
首页 > 其他好文 > 详细

HYSBZ - 1031 字符加密Cipher

时间:2017-10-25 23:56:44      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:break   超过   space   jsoi07   fine   put   https   包含   width   

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

 技术分享

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

Input

  输入文件包含一行,欲加密的字符串。注意字符串的内容不一定是字母、数字,也可以是符号等。

Output

  输出一行,为加密后的字符串。

Sample Input

JSOI07

Sample Output

I0O7SJ

Hint

 

对于100%的数据字符串的长度不超过100000。

 

做法:

后缀数组模板题,把字符串按自己本身扩充一次,求后缀数组即可。

代码:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1050010;
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
int wa[MAXN*3],wb[MAXN*3],wv[MAXN*3],wss[MAXN*3];
int c0(int *r,int a,int b)
{
return r[a] == r[b] && r[a+1] == r[b+1] && r[a+2] == r[b+2];
} 
int c12(int k,int *r,int a,int b)
{
if(k == 2)
return r[a] < r[b] || ( r[a] == r[b] && c12(1,r,a+1,b+1) );
else return r[a] < r[b] || ( r[a] == r[b] && wv[a+1] < wv[b+1] );
}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = 0;i < n;i++)wv[i] = r[a[i]]; for(i = 0;i < m;i++)wss[i] = 0; for(i = 0;i < n;i++)wss[wv[i]]++;
for(i = 1;i < m;i++)wss[i] += wss[i-1];
for(i = n-1;i >= 0;i--)
b[--wss[wv[i]]] = a[i];
}
void dc3(int *r,int *sa,int n,int m)
{
int i, j, *rn = r + n;
int *san = sa + n, ta = 0, tb = (n+1)/3, tbc = 0, p; r[n] = r[n+1] = 0;
for(i = 0;i < n;i++)if(i %3 != 0)wa[tbc++] = i; sort(r + 2, wa, wb, tbc, m);
sort(r + 1, wb, wa, tbc, m);
sort(r, wa, wb, tbc, m);
for(p = 1, rn[F(wb[0])] = 0, i = 1;i < tbc;i++) rn[F(wb[i])] = c0(r, wb[i-1], wb[i]) ? p - 1 : p++;
if(p < tbc)dc3(rn,san,tbc,p);
else for(i = 0;i < tbc;i++)san[rn[i]] = i;
for(i = 0;i < tbc;i++) if(san[i] < tb)wb[ta++] = san[i] * 3;
if(n % 3 == 1)wb[ta++] = n - 1; sort(r, wb, wa, ta, m);
for(i = 0;i < tbc;i++)wv[wb[i] = G(san[i])] = i;
for(i = 0, j = 0, p = 0;i < ta && j < tbc;p++)
sa[p] = c12(wb[j] % 3, r, wa[i], wb[j]) ? wa[i++] : wb[j++];
for(;i < ta;p++)sa[p] = wa[i++];
for(;j < tbc;p++)sa[p] = wb[j++];
} 
char s[MAXN]; 
int a[MAXN];
int sa[MAXN];
int main()
{
	while(gets(s)!=NULL)
	{
	int n=strlen(s);
	for (int i=n;i<2*n;i++) s[i]=s[i-n];
	for (int i=0;i<2*n;i++) a[i]=s[i];
	a[2*n]=0;
	dc3(a,sa,2*n+1,300);
	int num=0;
	for (int i=1;i<=2*n;i++){
		int p; 
	//	cout<<s+sa[i]<<endl;continue;
		if (2*n-sa[i]<n||sa[i]>=n) continue;
		num++;
		p=sa[i]+n-1;
		putchar(s[p]);
		if(num>=n) break;
		}
	}
    return 0;
}

  

HYSBZ - 1031 字符加密Cipher

标签:break   超过   space   jsoi07   fine   put   https   包含   width   

原文地址:http://www.cnblogs.com/xfww/p/7732533.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!