您的位置:首页 > 其它

bzoj4104【THUSC2015】解密运算

2016-06-01 23:23 519 查看

4104: [Thu Summer Camp 2015]解密运算

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 301  Solved: 190

[Submit][Status][Discuss]

Description

 对于一个长度为N的字符串,我们在字符串的末尾添加一个特殊的字符"."。之后将字符串视为一个环,从位置1,2,3,...,N+1为起点读出N+1个字符,就能得到N+1个字符串。

比如对于字符串“ABCAAA”,我们可以得到这N+1个串:

ABCAAA.

BCAAA.A

CAAA.AB

AAA.ABC

AA.ABCA

A.ABCAA

.ABCAAA

接着我们对得到的这N+1个串按字典序从小到大进行排序(注意特殊字符“.”的字典序小于任何其他的字符)结果如下:

.ABCAAA

A.ABCAA

AA.ABCA

AAA.ABC

ABCAAA.

BCAAA.A

CAAA.AB

最后,将排序好的N+1个串的最后一个字符取出,按照顺序排成一个新的字符串,也就是上面这个表的最后一列,就是加密后的密文“AAAC.AB”。

请通过加密后的密文求出加密前的字符串。

Input

第一行有两个整数N,M,分别表示加密前的字符串长度和字符集大小,其中字符用整数1,2,3,...,M编号,添加的特殊字符“."用0编号。

第二行为N+1个整数,表示加密后的字符串。

Output

输出仅一行,包含N个整数,用空格隔开,依次表示加密前字符串中每个字符的编号。

Sample Input

6 3

1 1 1 3 0 1 2

Sample Output

1 2 3 1 1 1

HINT

 #i (i=1~4)    N=5*(i+1) M<=3

#5~6    N,M<=50 字符串中字符互不相同

#7~8    N,M<=1000 字符串中字符互不相同

#9~12    N,M<=1000

#13~#20    N,M<=200000

Source

鸣谢佚名上传

这道题思路很妙,代码很短,看了题解是深深的无力感...

首先每个数能给我们两个信息:这个数是什么,这个数后面第一个数开头的字符串的排名。

所以我们只要知道每个数开头字符串的排名,就可以依次推出每一个数是多少。

所以问题就是如何求这个排名,实际上就是求后缀数组。

考虑两个字符串,如果首字母不同,那顺序很好确定;如果首字母不同,就要比较下一个字母,而下一个字母的排名实际已经给出了,就是读入的序号。

所以我们将读入的序列,以权值为第一关键字,序号为第二关键字排序。

这样就得到第一个数开头的字符串的排名,就能知道第一个数是多少,然后就得到第二个数开头的字符串的排名,又可以知道第二个数是多少……按这个顺序就可以得到每一个数了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define pa pair<int,int>
#define N 200005
using namespace std;
int n,m;
pa a
;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int main()
{
n=read();m=read();
F(i,0,n) a[i].first=read(),a[i].second=i;
sort(a,a+n+1);
int tmp=a[0].second;
F(i,1,n)
{
printf("%d ",a[tmp].first);
tmp=a[tmp].second;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: