首页 > 代码库 > BZOJ 1031 JSOI2007 字符加密Cipher 后缀数组
BZOJ 1031 JSOI2007 字符加密Cipher 后缀数组
题目大意:给定一个字符串,求将这个字符串首尾相接后以每个字符开头的字符串排序后最后一列的字符串
传说中的后缀数组0.0 昨晚看了一晚上DC3没看懂,于是写了倍增0.0 罗先生的25行代码实在是抽象QAQ 蒟蒻表示理解不能QAQ 于是自己写了个比较清晰的版本QAQ
首先这题是环 于是我们把字符串的前n-1个字符添加到这个字符串的尾端 然后就是后缀数组的事情了
求完这个之后按照后缀数组的顺序枚举每个开头看看是不是长度大于等于n就行了
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 200200 using namespace std; int n,rank[M],sa[M]; char s[M]; int X[M],Y[M]; void Get_Rank() { int i,j,tot=0; static pair<char,int>t[M]; for(i=1;i<=n;i++) t[i]=make_pair(s[i],i); sort(t+1,t+n+1); for(i=1;i<=n;i++) { if(i==1||t[i].first!=t[i-1].first) ++tot; rank[t[i].second]=tot; } } void Radix_Sort(int key[],int order[]) { int i; static int sum[M],cnt[M],temp[M]; memset(sum,0,sizeof sum); memset(cnt,0,sizeof cnt); for(i=1;i<=n;i++) sum[ key[i] ]++; for(i=1;i<=n;i++) sum[i]+=sum[i-1]; for(i=1;i<=n;i++) temp[ sum[key[order[i] ]-1]+ ++cnt[ key[order[i] ] ] ]=order[i]; memcpy(order,temp,sizeof temp); } void Prefix_Doubling() { int i,j,tot; Get_Rank(); for(j=1;j<=n;j<<=1) { for(i=1;i<=n;i++) { X[i]=rank[i]; Y[i]=i+j>n?0:rank[i+j]; sa[i]=i; } Radix_Sort(Y,sa); Radix_Sort(X,sa); for(i=1,tot=0;i<=n;i++) { if( i==1 || X[sa[i]]!=X[sa[i-1]] || Y[sa[i]]!=Y[sa[i-1]] ) ++tot; rank[sa[i]]=tot; } } } int main() { int i; scanf("%s",s+1); n=strlen(s+1); memcpy(s+n+1,s+1,n-1); n=n+n-1; Prefix_Doubling(); for(i=1;i<=n;i++) if(sa[i]+(n>>1)<=n) putchar(s[sa[i]+(n>>1)]); cout<<endl; return 0; }
BZOJ 1031 JSOI2007 字符加密Cipher 后缀数组
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。