秘密信息
hidden.c/cpp/pas
(1s/256M)
【题目描述】
Irene想用以下的方法加密一条信息(这是她从密码学书上自学来的):
假定这条信息可以用一个字符串S表示,其中S=BCAAD.(其中‘.’代表字符串结尾)。Irene首先把S的所有循环同构串写下来(所谓循环同构即是不断地把字符串开头的字符移动到尾端):
BCAAD.
CAAD.B
AAD.BC
AD.BCA
D.BCAA
.BCAAD
接下来她会把这些字符串都排序:
.BCAAD
AAD.BC
AD.BCA
BCAAD.
CAAD.B
D.BCAA
接下来她会把这些字符串的最后一位按照顺序写下来得到加密串T=DCA.BA
现在Irene发现在密码学的书上写着一条来历不明的加密串T。她迫切地知道,如果信息是按照这种方式加密的,那么原串是什么?
【输入格式】hidden.in
一行一个由大写字母构成,长度为N的字符串(但字符串有且只有一个’.’)。
【输出格式】hidden.out
输出一行,输出原串。数据保证有唯一解。
【样例输入1】
PH.EL
【样例输出1】
HELP.
【样例输入2】
BBA.AA
【样例输出2】
ABAAB.
【数据范围与约束】
对于20%的数据,2<=N<=10;
对于50%的数据,2<=N<=27, 字符串内部的字母互不相同。
对于100%的数据,2<=N<=30000。
五十分的话,我们以字母坐下标,把它后面的字母存在数组里就能很简单地写出。
#include<iostream> #include<queue> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int a[30009],len,b[30009]; int ans[30009]; char s[30009]; int nex[30],h; int main()//50 { freopen("hidden.in","r",stdin); freopen("hidden.out","w",stdout); cin>>s; len=strlen(s); for(int i=0;i<len;i++) a[i]=s[i]-'A'+1,b[i]=a[i]; ans[len-1]=a[0]; sort(a,a+len); for(int i=0;i<len;i++) { if(b[i]>0) nex[b[i]]=a[i]; else h=a[i]; } int now=h; while(now>0) { printf("%c",now+'A'-1); now=nex[now]; } printf(". "); return 0; }
100分的话,字母会有重复。存在这样一个规律先出现在左列的字母,先出现在右列
#include<iostream> #include<queue> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int N=3000009; int a[N],len,b[N]; int sum[N]; char s[N]; int d[N],c[N]; int main() { freopen("hidden.in","r",stdin); freopen("hidden.out","w",stdout); cin>>s; len=strlen(s); for(int i = 0; i < len; ++ i) if(s[i] >= 'A') a[i] = s[i] - 'A' + 1; else a[i] = 0; for(int i = 0; i<len; ++ i) sum[a[i]] ++; for(int i=1;i<=30;i++) sum[i]+=sum[i-1]; for(int i=len-1;i>=0;i--) b[i]=--sum[a[i]]; for(int i=0;i<len;i++) d[b[i]]=i; for(int i=0,t=d[0];i<len;i++) c[i]=t,t=d[t]; for(int i = 0; i < len-1; ++ i) cout << char(a[d[c[i]]] + 'A' - 1); cout << ". " << endl; return 0; }