zoukankan      html  css  js  c++  java
  • 后缀排序(后缀数组初探

      题目链接:http://codevs.cn/problem/1500/

     

     后缀数组裸题。(不清楚概念的点这里

      代码及说明:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define LL long long
     6 #define RI register int
     7 using namespace std;
     8 const int INF = 0x7ffffff ;
     9 const int N = 15000 + 10 ;
    10 
    11 inline int read() {
    12     int k = 0 , f = 1 ; char c = getchar() ;
    13     for( ; !isdigit(c) ; c = getchar())
    14       if(c == '-') f = -1 ;
    15     for( ; isdigit(c) ; c = getchar())
    16       k = k*10 + c-'0' ;
    17     return k*f ;
    18 }
    19 int n, k, p, q = 1 ; 
    20 int a[N], v[N], sa[2][N], rk[2][N] ; // 滚动数组实现 
    21 char s[N] ;
    22 
    23 inline void mul(int *sa,int *rk,int *SA,int *RK) {  // 前一个状态 -> 后一个状态 
    24     for(int i=1;i<=n;i++) v[rk[sa[i]]] = i ;  // v[i]表示权值小于等于为i的有多少个(此时权值为上一状态中的排名)
    25                                               // sa[i]的排名属于区间 ( v[rk[sa[i]]-1] , v[rk[sa[i]]] ] 
    26     for(int i=n;i;i--) if(sa[i] > k) SA[v[rk[sa[i]-k]]--] = sa[i]-k ;  // 按第二关键字由大到小的顺序排序 
    27     for(int i=n-k+1;i<=n;i++) SA[v[rk[i]]--] = i ;  // 把没有第二关键字的排序 
    28     for(int i=1;i<=n;i++) RK[SA[i]] = RK[SA[i-1]] + (rk[SA[i]] != rk[SA[i-1]] || rk[SA[i]+k] != rk[SA[i-1]+k]) ;
    29 }
    30 inline void presa() {
    31     for(int i=1;i<=n;i++) v[a[i]]++ ;  // 放入桶中 ( v[i]表示权值为i的有多少个 
    32     for(int i=1;i<=26;i++) v[i] += v[i-1] ;  // 维护前缀和 , 则对于i,rk[i]一定在 ( v[a[i]-1] , v[a[i]] ] 中。 
    33     for(int i=1;i<=n;i++) sa[p][v[a[i]]--] = i ;  // p表示当前状态,先不用管
    34                                                   // sa[i]表示的是权值第i小的后缀(此时是单个字符)的第一个字符的数组下标
    35     for(int i=1;i<=n;i++) rk[p][sa[p][i]] = rk[p][sa[p][i-1]] + (a[sa[p][i]] != a[sa[p][i-1]]) ; // sa是按权值排序的,若权值与前一个相同,那么排名也与前一个相同;否则 + 1 
    36     for(k=1;k<n;k<<=1,swap(p,q)) {  // 倍增求sa数组(求后缀长度为k的sa数组 
    37         mul(sa[p],rk[p],sa[q],rk[q]) ;  // p表示前一个状态(即后缀长度为k-1),q表示当前状态(即后缀长度为k) 
    38         if(rk[p][sa[q][n]] == n) {   // 剪枝 (第n小的排名为n证明前面没有相同的,则无需进行下去 
    39             swap(p,q) ; return ;
    40         }
    41     }
    42 }
    43 
    44 int main() {
    45     n = read() ; scanf("%s",s+1) ;
    46     for(int i=1;i<=n;i++) a[i] = s[i]-'a'+1 ;  
    47     presa() ; // 获得sa数组 
    48     for(int i=1;i<=n;i++) printf("%d
    ",sa[p][i]) ;
    49     return 0 ;
    50 }
  • 相关阅读:
    机器人学 —— 轨迹规划(Artificial Potential)
    机器人学 —— 轨迹规划(Sampling Method)
    机器人学 —— 轨迹规划(Configuration Space)
    机器人学 —— 机器人感知(Kalman Filter)
    机器人学 —— 机器人感知(Gaussian Model)
    机器学习 —— 概率图模型(Homework: Structure Learning)
    机器人学 —— 机器人视觉(Bundle Adjustment)
    机器人学 —— 机器人视觉(极几何)
    机器学习 —— 概率图模型(Homework: CRF Learning)
    机器人学 —— 机器人视觉(估计)
  • 原文地址:https://www.cnblogs.com/zub23333/p/8664652.html
Copyright © 2011-2022 走看看