uoj #35. 后缀排序
2017-04-09 19:54
260 查看
【分析】
倍增法求后缀数组的rank & sa。参考注释来理解。
【代码】
【代码】
对height数组的求法稍做改进
倍增法求后缀数组的rank & sa。参考注释来理解。
【代码】
//uoj #35. 后缀排序 #include<iostream> #include<cstdio> #include<cstring> #define fo(i,j,k) for(i=j;i<=k;i++) using namespace std; const int mxn=100005; int n,m=126,len; int sa[mxn],x[mxn],y[mxn],b[mxn],a[mxn],rank[mxn],height[mxn]; char s[mxn]; inline bool comp(int i,int j,int l) //比较rank是否相同 { return y[i]==y[j]&&(i+l>=len?-1:y[i+l])==(j+l>=len?-1:y[j+l]); } inline void work() { int i,j,k,p; fo(i,0,m) b[i]=0; //把桶清零 fo(i,0,len-1) b[x[i]=a[i]]++; fo(i,1,m) b[i]+=b[i-1]; for(i=len-1;i>=0;i--) sa[--b[x[i]]]=i; //第一次排序 for(k=1;k<=len;k<<=1) { p=-1; for(i=len-k;i<=len-1;i++) y[++p]=i; //第二关键字为0的数 fo(i,0,len-1) if(sa[i]>=k) y[++p]=sa[i]-k; //与上一行构成第二关键字排序 fo(i,0,m) b[i]=0; fo(i,0,len-1) b[x[y[i]]]++; fo(i,1,m) b[i]+=b[i-1]; for(i=len-1;i>=0;i--) sa[--b[x[y[i]]]]=y[i]; // fo(i,0,len-1) printf("%d ",sa[i]);printf("\n"); swap(x,y);p=1;x[sa[0]]=0; //y储存旧的rank fo(i,1,len-1) x[sa[i]]=comp(sa[i-1],sa[i],k)?p-1:p++; //x储存新的rank if(p>=len) break; m=p; } p=0; //暴力搞出来height fo(i,0,len-1) rank[sa[i]]=i; fo(i,0,len-1) { if(!rank[i]) continue; j=sa[rank[i]-1]; while(i+p<len && j+p<len && s[i+p]==s[j+p]) p++; height[rank[i]]=p; //rank[i]与rank[i-1]的lcp p=max(0,p-1); } } int main() { int i,j,k; scanf("%s",s); len=strlen(s); fo(i,0,len-1) a[i]=s[i]-'a'+1; work(); fo(i,0,len-1) printf("%d ",sa[i]+1);printf("\n"); fo(i,1,len-1) printf("%d ",height[i]);printf("\n"); return 0; }
【代码】
对height数组的求法稍做改进
//uoj #35. 后缀排序 #include<iostream> #include<cstdio> #include<cstring> #define fo(i,j,k) for(i=j;i<=k;i++) using namespace std; const int mxn=100005; int n,m=126,len; int sa[mxn],x[mxn],y[mxn],b[mxn],a[mxn],rank[mxn],height[mxn]; char s[mxn]; inline bool comp(int i,int j,int l) //比较rank是否相同 { return y[i]==y[j]&&(i+l>len?-1:y[i+l])==(j+l>len?-1:y[j+l]); } inline void work() { int i,j,k,p; fo(i,0,m) b[i]=0; //把桶清零 fo(i,1,len) b[x[i]=a[i]]++; fo(i,1,m) b[i]+=b[i-1]; for(i=len;i>=1;i--) sa[b[x[i]]--]=i; //第一次排序 for(k=1;k<=len;k<<=1) { p=0; for(i=len-k+1;i<=len;i++) y[++p]=i; //第二关键字为0的数 fo(i,1,len) if(sa[i]>k) y[++p]=sa[i]-k; //与上一行构成第二关键字排序 fo(i,0,m) b[i]=0; fo(i,1,len) b[x[y[i]]]++; fo(i,1,m) b[i]+=b[i-1]; for(i=len;i>=1;i--) sa[b[x[y[i]]]--]=y[i]; swap(x,y);p=2;x[sa[1]]=1; //y储存旧的rank fo(i,2,len) x[sa[i]]=comp(sa[i-1],sa[i],k)?p-1:p++; //x储存新的rank if(p>len) break; m=p-1; } p=k= 4000 0; //暴力搞出来height fo(i,1,len) rank[sa[i]]=i; for(i=1;i<=len;height[rank[i++]]=k) for(k?k--:0,j=sa[rank[i]-1];s[i+k]==s[j+k];k++); } int main() { int i,j,k; scanf("%s",s+1); len=strlen(s+1); fo(i,1,len) a[i]=s[i]-'a'+1; work(); fo(i,1,len) printf("%d ",sa[i]);printf("\n"); fo(i,2,len) printf("%d ",height[i]);printf("\n"); return 0; } //ededdddeddeeddded
相关文章推荐
- Uoj#35. 后缀排序
- UOJ #35. 后缀排序 后缀数组模板题
- UOJ #35. 后缀排序(后缀数组模板题)
- uoj#35. 后缀排序 后缀数组
- [省选前题目整理][UOJ 35]后缀排序(后缀数组)
- UOJ #35. BZOJ 1031 后缀排序 后缀数组模板
- Uoj #35. 后缀排序(后缀数组)
- 【后缀数组】uoj#35. 后缀排序
- 【UOJ 35】 后缀排序|后缀数组 *2
- UOJ #35. 后缀排序[后缀数组详细整理]
- 【UOJ 35】 后缀排序|后缀数组 *3
- 【uoj 35】后缀排序
- 【UOJ 35】 后缀排序|后缀数组
- uoj P35 后缀排序
- Codevs 1500 后缀排序(后缀数组)
- jobdu 题目1099:后缀子串排序
- 九度OJ1099:后缀子串排序解题报告
- uoj#35: 后缀排序
- uoj35: 后缀排序
- 【BZOJ4199&UOJ131】品酒大会(后缀数组,并查集)