zoukankan      html  css  js  c++  java
  • UOJ #35. 后缀排序 后缀数组 模板

    http://uoj.ac/problem/35

    模板题,重新理了一遍关系。看注释吧。充分理解了倍增的意义,翻倍之后对上一次排序的利用是通过一种类似于队列的方式完成的。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 const int maxn=200010;
     8 const int pl=50;
     9 int sa[maxn+pl]={};//排名第i的是从sa[i]开始的数组
    10 int rk[maxn+pl]={};//i的排名
    11 int height[maxn+pl]={};//排名第i的与排名第i-1的最长相同前缀长度
    12 int temp[maxn+pl]={};//暂时的排名
    13 int cnt[maxn+pl]={};//第i种(字典序)前缀的有多少个(的前缀和)
    14 int p[maxn+pl]={};//此次需要排列的sa的储存,处理了后缀长度不同的情况。
    15 char ch[maxn+pl]={};
    16 int siz;
    17 bool equ(int x,int y,int l){ return rk[x]==rk[y]&&rk[x+l]==rk[y+l]; }
    18 void SA(){
    19     for(int i=1;i<=siz;i++){rk[i]=ch[i];sa[i]=i;}
    20     for(int i,sig=255,l=0,pos=0;pos<siz;sig=pos){
    21         pos=0;
    22         for(i=siz-l+1;i<=siz;i++)p[++pos]=i;//根据上一次的sa决定p的储存顺序,没有排序则排在最前。
    23         for(i=1;i<=siz;i++) if(sa[i]>l) p[++pos]=sa[i]-l;//sa的计算是向字符串前端(左侧)拓展的
    24         for(i=1;i<=sig;i++) cnt[i]=0;
    25         for(i=1;i<=siz;i++) cnt[rk[p[i]]]++;
    26         for(i=1;i<=sig;i++) cnt[i]+=cnt[i-1];
    27         for(i=siz;i>0;i--) sa[cnt[rk[p[i]]]--]=p[i];//方便记忆板子的提示,只有这里是倒着扫的。
    28         pos=0;
    29         for(i=1;i<=siz;i++){
    30             if(equ(sa[i],sa[i-1],l))temp[sa[i]]=pos;
    31             else temp[sa[i]]=++pos;
    32         }
    33         for(int i=1;i<=siz;i++)rk[i]=temp[i];
    34         if(!l)l=1;
    35         else l<<=1;
    36     }int j=0;
    37     for(int i=1;i<=siz;i++){
    38         if(rk[i]==1){j=0;continue;}
    39         if(j)j--;
    40         while(ch[i+j]==ch[sa[rk[i]-1]+j]){
    41             j++;
    42         }height[rk[i]]=j;
    43     }
    44 }
    45 int main(){
    46     //freopen("a.in","r",stdin);
    47     scanf("%s",ch+1);siz=strlen(ch+1);
    48     SA();
    49     for(int i=1;i<=siz;i++)printf("%d ",sa[i]);
    50     cout<<endl;
    51     for(int i=2;i<=siz;i++)printf("%d ",height[i]);
    52     return 0;
    53 }
    View Code

  • 相关阅读:
    Linux 下安装JDK1.8
    Linux 常规操作
    C3P0连接池拒绝连接
    Oracle查看并修改最大连接数
    Oracle 建立 DBLINK
    Oracle 数据 update后怎么恢复到以前的数据
    Oracle 11g中解锁被锁定的用户
    身份证15位转18位
    Druid数据库连接池
    CentOS 下安装 LEMP 服务(Nginx、MariaDB/MySQL 和PHP)
  • 原文地址:https://www.cnblogs.com/137shoebills/p/8511439.html
Copyright © 2011-2022 走看看