bzoj 1031: [JSOI2007]字符加密Cipher
题目链接
bzoj 1031: [JSOI2007]字符加密Cipher
后缀数组裸题。
把字符串接到自己后面后直接排序。
输出结尾字符就好了QAQ
/**************************************************************
Problem: 1031
Language: C++
Result: Accepted
Time:1588 ms
Memory:21328 kb
****************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
const int maxn = 1000007;
int saf[maxn],sa[maxn],rank[maxn],cnt[maxn],s[maxn];
char a[maxn];
int n,m,st;
inline void rsort() {
for(int i=0;i<=m;++i) cnt[i]=0;
for(int i=1;i<=n;++i) cnt[rank[saf[i]]]++;
for(int i=1;i<=m;++i) cnt[i]+=cnt[i-1];
for(int i=n;i>=1;--i) sa[cnt[rank[saf[i]]]--]=saf[i];
}
inline bool cmp(int *f,int x,int y,int w) {
return f[x]==f[y]&&f[x+w]==f[y+w];
}
void get_sa() {
for(int i=1;i<=n;++i) rank[i]=s[i],saf[i]=i;m=125;
rsort();
for(int p=0,w=1;p<n;w<<=1,m=p) {
p=0;
for(int i=n-w+1;i<=n;++i) saf[++p]=i;
for(int i=1;i<=n;++i)
if(sa[i]>w) saf[++p]=sa[i]-w;
rsort();
std::swap(rank,saf);rank[sa[1]]=p=1;
for(int i=2;i<=n;++i) rank[sa[i]]=cmp(saf,sa[i],sa[i-1],w)? p:++p;
}
for(int i=1;i<=n;++i) if(sa[i]<=st)printf("%c",a[sa[i]+st-1]);
}
int main() {
scanf("%s",a+1);
st=n=strlen(a+1);
for(int i=1;i<n;++i)a[i+n]=a[i];
n=n*2-1;
for(int i=1;i<=n;++i) s[i]=a[i],s[i+n]=s[i];
s[0]=s[n+1]=-1;
get_sa();
return 0;
}