zoukankan      html  css  js  c++  java
  • 【tyvj1860】后缀数组

    描述
    我们定义一个字符串的后缀suffix(i)表示从s[i]到s[length(s)]这段子串。
    后缀数组(Suffix array)SA[i]中存放着一个排列,满足suffix(sa[i])<suffix(sa[i+1]) 按照字典序方式比较
    定义height[i]表示suffix(sa[i])与suffix(sa[i-1])之间的最长公共前缀长度,其中height[1]=0
    你的任务就是求出SA和height这两个数组。字符串长度<=200000

    输入格式

    一行,为描述中的字符串(仅会出现小写字母)

    输出格式

    共两行,每行n个数,第一行为sa[i],第二行为height[i],其中每行的数均用空格隔开

    测试样例1

    输入

    aabaaaab

    输出

    4 5 6 1 7 2 8 3 
    0 3 2 3 1 2 0 1
    题目告诉我们这是一个模板题,这的确就是一个模板题,geth函数还不是太理解。
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<set>
     6 #include<ctime>
     7 #include<vector>
     8 #include<cmath>
     9 #include<algorithm>
    10 #include<map>
    11 #define inf 2000000000
    12 #define N 200005
    13 int n;
    14 char ch[N];
    15 int a[N],h[N];
    16 int v[N];
    17 int sa[2][N],rk[2][N];
    18 int p,q,k;
    19 void init(){
    20     scanf("%s",ch+1);
    21     n=strlen(ch+1);
    22     for (int i=1;i<=n;i++) a[i]=ch[i]-'a'+1;
    23 }
    24 
    25 void change(int sa[N],int rk[N],int SA[N],int RK[N]){
    26     for (int i=1;i<=n;i++) v[rk[sa[i]]]=i;//该排名最后出现的位置
    27     for (int i=n;i>=1;i--) if (sa[i]>k)
    28         SA[v[rk[sa[i]-k]]--]=sa[i]-k;//sa[i]-k代表一个字符串
    29     for (int i=n-k+1;i<=n;i++) SA[v[rk[i]]--]=i;//?
    30     for (int i=1;i<=n;i++)  RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i-1]]!=rk[SA[i]]||rk[SA[i-1]+k]!=rk[SA[i]+k]);
    31     
    32 }
    33 
    34 void work(){
    35      q=1,p=0;
    36     for (int i=1;i<=n;i++) v[a[i]]++;
    37     for (int i=1;i<=26;i++)v[i]+=v[i-1];
    38     for (int i=1;i<=n;i++) sa[p][v[a[i]]--]=i;
    39     for (int i=1;i<=n;i++) rk[p][sa[p][i]]=(rk[p][sa[p][i-1]])+(a[sa[p][i-1]]!=a[sa[p][i]]);
    40     k=1;
    41     while (k<n){
    42         change(sa[p],rk[p],sa[q],rk[q]);
    43         p^=1;q^=1;k=k<<1;
    44     }
    45     for (int i=1;i<=n;i++) printf("%d ",sa[p][i]);
    46 }
    47 
    48 void geth(){
    49     int k=0;
    50     for (int i=1;i<=n;i++)
    51     if (rk[p][i]==1)h[rk[p][i]]=0;
    52     else{
    53         int j=sa[p][rk[p][i]-1];
    54         while (a[i+k]==a[j+k])k++;
    55         h[rk[p][i]]=k;if (k>0)k--;
    56     }
    57 }
    58 
    59 int main(){
    60     init();
    61     work();
    62     geth();
    63     puts("");
    64     for(int i=1;i<=n;i++)printf("%d ",h[i]);
    65 }
  • 相关阅读:
    IIS配置
    sql表值函数中实现类似split功能
    毕至居预约系统设计图第十二组
    毕至居预约系统研发需求分析——第十二组
    MASA Blazor多页签组件
    关于Linux Oracle下的表空间文件删除不干净的处理方法
    命令行下对apk签名
    android自定义绘制TableLayout,类似.net中DataGrid控件
    使用Arcgis tools fix后Android不能生成Apk包异常解决方法
    SyncML一种平台无关的信息同步标准协议
  • 原文地址:https://www.cnblogs.com/wuminyan/p/5154181.html
Copyright © 2011-2022 走看看