【后缀数组之height数组】
模板奉上
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数组】的更多相关文章
- 【POJ2774】Long Long Message(后缀数组求Height数组)
点此看题面 大致题意: 求两个字符串中最长公共子串的长度. 关于后缀数组 关于\(Height\)数组的概念以及如何用后缀数组求\(Height\)数组详见这篇博客:后缀数组入门(二)--Height ...
- 后缀数组入门(二)——Height数组与LCP
前言 看这篇博客前,先去了解一下后缀数组的基本操作吧:后缀数组入门(一)--后缀排序. 这篇博客的内容,主要建立于后缀排序的基础之上,进一步研究一个\(Height\)数组以及如何求\(LCP\). ...
- 关于后缀数组的倍增算法和height数组
自己看着大牛的论文学了一下后缀数组,看了好久好久,想了好久好久才懂了一点点皮毛TAT 然后就去刷传说中的后缀数组神题,poj3693是进化版的,需要那个相同情况下字典序最小,搞这个搞了超久的说. 先简 ...
- 后缀数组的一些性质----height数组
height数组:定义 height[i] = suffix[i-1] 和 suffix[i] 的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀.那么对于 j 和 k 不妨设 Rank[j] & ...
- BZOJ2251 [2010Beijing Wc]外星联络 后缀数组 + Height数组
Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in", "r", stdin ...
- 洛谷P2408 不同子串个数 后缀数组 + Height数组
## 题目描述: 给你一个长为 $N$ $(N<=10^5)$ 的字符串,求不同的子串的个数我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样.子串的定义:原字 ...
- luogu P2852 [USACO06DEC]牛奶模式Milk Patterns 后缀数组 + Height数组 + 二分答案 + 扫描
后缀数组有一个十分有趣的性质: $height[rk[i]] >= height[rk[i-1]] - 1$ Code: #include <bits/stdc++.h> #d ...
- Java后缀数组-求sa数组
后缀数组的一些基本概念请自行百度,简单来说后缀数组就是一个字符串所有后缀大小排序后的一个集合,然后我们根据后缀数组的一些性质就可以实现各种需求. public class MySuffixArrayT ...
- 【后缀数组之SA数组】【真难懂啊】
基本上一搜后缀数组网上的模板都是<后缀数组——处理字符串的有力工具>这一篇的注释,O(nlogn)的复杂度确实很强大,但对于初次接触(比如窝)的人来说理解起来也着实有些困难(比如窝就活活好 ...
随机推荐
- 新手C#ListView使用记录2018.08.03
在使用C#的ListView时,感觉有一些部分需要自己注意. ListView1.Clear()这条指令在使用时,用于Click后在ListView中显示数据,应该放在输入数据的前面. 在ListVi ...
- 一张图片优化5k带来的带宽成本及其前端页面的优化方法
上周,我参加了公司的一门课程<网站性能优化>,讲师提出了一个问题:一张图片优化后减少5K,1年内可以大概省下多少宽带成本呢?非常好奇,仔细听完讲师分析,计算出来的数据让小伙伴们都惊呆了,仅 ...
- 在SharePoint解决方案中使用JavaScript (2) – 模块化
本文是在SharePoint中使用JavaScript的第二篇文章,前面的文章包括: 在SharePoint解决方案中使用JavaScript (0) 在SharePoint解决方案中使用JavaSc ...
- js动态的给json对象添加新的元素
把{name:"xxx",age:"xxx"}变成{name:"xxx",age:"xxx",value:"x ...
- adf错误
1>无法验证事务处理中的所有行 运行项目报错: javax.faces.el.EvaluationException: oracle.jbo.TxnValException: JBO-27023 ...
- 软件测试流程(Test Flow)
Bug Status Definition Bug Management Process Outline Bug Severity&Priority Criteria Definition
- tp5 sql 大于小于
1.大于 $rwhere['ctime'] = array('egt',10000); 2.小于 $rwhere[);
- block functions区块函数插件的定义与使用
在插件目录plugins里新建文件 block.插件名.php文件(如 block.插件名.php) 例:block.test2.php <?php function smarty_block_ ...
- shared_ptr / weak_ptr 代码片段
参考<<Boost程序库完全开放指南>> shared_ptr 类摘要(只列出了常用的部分)和相关说明 template <class T> class shar ...
- Perl 学习笔记-模块
1.Perl模块介绍 2个来源, 一个是随Perl发行版本一同打包, 只要安装了Perl就可以使用; 另一种是需要从CPAN上下载,自己安装. 寻找模块之前, 先检查系统上是否已经安装过了, ...