模板奉上

int rank[maxn],height[maxn];
void calheight(int *r,int *sa,int n)
{
int i,j,k=;
for(i=;i<=n;i++) rank[sa[i]]=i;
for(i=;i<n;height[rank[i++]]=k)
  for(k?k--:,j=sa[rank[i]-];r[i+k]==r[j+k];k++) //求h[i] = height[rank[i]];
      ;
return;
}

概念:

(1)height 数组:定义height[i]=suffix(SA[i-1])和suffix(SA[i])的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀的长度 。

(2)h[i]=height[rank[i]],也就是suffix(i)和排序后在它前一名的后缀的最长公共前缀的长度。

(3)函数lcp(u,v)=max{i|u=v},也就是从头开始顺次比较u和v的对应字符,对应字符持续相等的最大位置,称为这两个字符串u,v的最长公共前缀的长度。

(4)LCP(i,j):对正整数i,j 定义LCP(i,j)=lcp(Suffix(SA[i]),Suffix(SA[j]),其中i,j 均为1至n的整数。LCP(i,j)也就是后缀数组中第i个和第j个后缀的最长公共前缀的长度。

性质

(1)LCP(i,j)=min{height[k]|i+1≤k≤j},也就是说,计算LCP(i,j)等同于询问一维数组height[] 中下标在i+1 到j 范围内的所有元素的最小值。

(2)对于i>1 且Rank[i]>1,一定有h[i]≥h[i-1]-1。(这条性质要好好理解!)

  证明:设suffix(k)是排在suffix(i-1)前一名的后缀,它们的最长公共前缀是h[i-1]。

那么suffix(k+1)将排在suffix(i)的前面(这里要求h[i-1]>1,如果h[i-1]≤1,原式显然成立)并且suffix(k+1)和suffix(i)的最长公共前缀是h[i-1]-1,

所以suffix(i)和在它前一名的后缀的最长公共前缀至少是h[i-1]-1。

按照h[1],h[2],……,h[n]的顺序计算,并利用h 数组的性质,时间复杂度可以降为O(n)。

  即:

   rank[i-1] = q-1 suffix(k):        rabaa

   rank[i-1] = q    suffix(i-1):    racadabrabaa         h[i-1] = 2;

   ......

   rank[k-1] = p-1   suffix(k-1):     abaa

   rank[i] = p          suffix(i):       acadabrabaa         h[i] = 1 (h[i] >= h[i-1]-1 = 1;)

 

计算数组h[]

可以令i从1循环到n(此循环中i的意义为suffix(i))按照如下方法依次算出h[i]:

  若 Rank[i]=1,则h[i]=0。字符比较次数为0。

  若i=1或者h[i-1]≤1,则直接将Suffix(i)和Suffix(Rank[i]-1)从第一个字符开始依次比较直到有字符不相同,由此计算出h[i]。字符比较次数为h[i]+1,不超过h[i]-h[i-1]+2。

  否则,说明i>1,Rank[i]>1,h[i-1]>1,根据性质2,Suffix(i)和Suffix(Rank[i]-1)至少有前h[i-1]-1 个字符是相同的,于是字符比较可以从h[i-1]开始,直到某个字符不相同,由此计算出h[i]。字符比较次数为h[i]-h[i-1]+2。

  可求得最后算法复杂度为O(n)。

【后缀数组之height数组】的更多相关文章

  1. 【POJ2774】Long Long Message(后缀数组求Height数组)

    点此看题面 大致题意: 求两个字符串中最长公共子串的长度. 关于后缀数组 关于\(Height\)数组的概念以及如何用后缀数组求\(Height\)数组详见这篇博客:后缀数组入门(二)--Height ...

  2. 后缀数组入门(二)——Height数组与LCP

    前言 看这篇博客前,先去了解一下后缀数组的基本操作吧:后缀数组入门(一)--后缀排序. 这篇博客的内容,主要建立于后缀排序的基础之上,进一步研究一个\(Height\)数组以及如何求\(LCP\). ...

  3. 关于后缀数组的倍增算法和height数组

    自己看着大牛的论文学了一下后缀数组,看了好久好久,想了好久好久才懂了一点点皮毛TAT 然后就去刷传说中的后缀数组神题,poj3693是进化版的,需要那个相同情况下字典序最小,搞这个搞了超久的说. 先简 ...

  4. 后缀数组的一些性质----height数组

    height数组:定义 height[i] = suffix[i-1] 和 suffix[i] 的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀.那么对于 j 和 k 不妨设 Rank[j] & ...

  5. BZOJ2251 [2010Beijing Wc]外星联络 后缀数组 + Height数组

    Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in", "r", stdin ...

  6. 洛谷P2408 不同子串个数 后缀数组 + Height数组

    ## 题目描述: 给你一个长为 $N$ $(N<=10^5)$ 的字符串,求不同的子串的个数我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样.子串的定义:原字 ...

  7. luogu P2852 [USACO06DEC]牛奶模式Milk Patterns 后缀数组 + Height数组 + 二分答案 + 扫描

    后缀数组有一个十分有趣的性质: $height[rk[i]] >= height[rk[i-1]] - 1$    Code: #include <bits/stdc++.h> #d ...

  8. Java后缀数组-求sa数组

    后缀数组的一些基本概念请自行百度,简单来说后缀数组就是一个字符串所有后缀大小排序后的一个集合,然后我们根据后缀数组的一些性质就可以实现各种需求. public class MySuffixArrayT ...

  9. 【后缀数组之SA数组】【真难懂啊】

    基本上一搜后缀数组网上的模板都是<后缀数组——处理字符串的有力工具>这一篇的注释,O(nlogn)的复杂度确实很强大,但对于初次接触(比如窝)的人来说理解起来也着实有些困难(比如窝就活活好 ...

随机推荐

  1. 高性能Web服务器Nginx的配置与部署研究(2)Nginx入门级配置与部署及“Hello World”

    1. Nginx 程序包 目前最新的开发版本时1.1.12: Linux/Unix:nginx-1.1.12.tar.gz Windows:nginx-1.1.12.zip 我们可以下载稳定版尝试: ...

  2. Spket,eclipse下安装Spket插件,格式化js

    点击菜单 Help => Install New SoftWare => add 如图 name框输入:Skept Location框输入:http://www.agpad.com/upd ...

  3. 346. Moving Average from Data Stream数据窗口流中位数的数据结构设计

    [抄题]: Given a stream of integers and a window size, calculate the moving average of all integers in ...

  4. Linux ftp Command

    一.ftp的get命令和mget命令有何不同? get一次只下载一个文件:mget一次可以下载多个文件,而且支持通配符,需要注意的是在mget的时侯,需要对每一个文件都选择y/n,如果想不交互的下载全 ...

  5. css实现水平伸缩菜单

    ul li a{transition:width 500ms ease;} a:hover{width:*;} 高度向上延伸用height:*;margin-top:-*px;//负值实现向上

  6. maven环境快速搭建(转)

    出处:http://www.cnblogs.com/fnng/archive/2011/12/02/2272610.html 最近,开发中要用到maven,所以对maven进行了简单的学习.因为有个m ...

  7. Spring MVC @RequestMapping浅析

    简介:@RequestMappingRequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上.用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径.RequestMapp ...

  8. windows10最实用的快捷键、高效的windows模式

    win+方向键 将软件窗口放置到方向 ctrl+win+左右方向键 切换虚拟桌面 win+tab 选择窗口或虚拟桌面,然后按着win随后放开,界面停留 alt+tab 切换窗口 ctrl+win+D ...

  9. 设计模式6---代理模式(Proxy Pattern)

    代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 1.  静态代理 静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象都实现相同的接口或者是继承相同父类. 接口:IUser ...

  10. ARM汇编中一些重要伪指令

    IMPORT ,定义表示这是一个外部变量的标号,不是在本程序定义的 EXPORT ,表示本程序里面用到的变量提供给其他模块调用的. 以上两个在汇编和C语言混合编程的时候用到 ENDP    表示PRO ...