算法学习:后缀数组 height的求取

【定义】

【LCP】全名最长公共前缀,两个后缀之间的最长前缀,以下我们定义

lcp ( i , j ) 的意义是后缀 i 和 j 的最长前缀

【z函数】 函数z [ i ] 表示的是,第 i 个后缀和字符串的最长前缀



 【解决问题】

这两个算法都是在解决这个问题

即求后缀和字符串和后缀之间的最长公共前缀

但是有所不同的是,

后缀数组最终求出的是,字典序第 i 个后缀和第 i + 1 个后缀的最长公共前缀

z函数最终求出的是,第 i 个后缀和字符串的最长公共前缀

然后通过这个最长公共前缀求一些其他的值



【算法学习】

【后缀数组】

  后缀数组能够在 n 的时间内求出字典序第 i 和第 i - 1 个后缀的最长公共前缀

而这个函数通常被命名为 height

height [ i ] 的含义为 , 字典序第 i - 1个后缀和第 i 个后缀的最长公共前缀

有以下几个性质进行求取:(s [ i ] 表示第 i 个后缀)

1.若 i 小于 j , LCP ( i , j )  = min { LCP ( k - 1 , k ), i + 1 <= k <= j }

  可利用此项用 RMQ 求LCP

2.定义 h [ i ] 为 :第 i 号开始的后缀和他字典序前面的后缀的LCP

  即: h [ i ] = height [ rank [ i ] ]

  于是有,对于 i > 1 且 rank [ i ]  > 1 有  

   h [ i ]  >  h [ i - 1 ] - 1 ;

   

  证明如下 :

  设 j 为 第 i - 1 号开始的后缀按排名的前面的那个后缀的开始的位置

  注意: j 不是第 i - 2号

  此时,第 j 个后缀和第 i - 1 个后缀的 LCP 在定义上为 height [ rank [ i - 1 ] ],即 h [ i - 1 ]

即我们要证明的右半部分的一部分

然后我们讨论 j + 1 和 i (由得到 i - 1 + 1 ) 的关系:

第一种,当 j 和 i - 1 首字母不相等的情况,h [ i - 1 ] 为 0

那么显然  h [ i ] > h [ i - 1 ] - 1

第二种,当 j 和 i - 1 首字母相等的情况,

那么显然,j 和 i - 1 的 LCP 为 h [ i - 1 ] - 1

在后缀中,排名比 i 考前,和后缀 i LCP最长的,相似度最高的显然是SA中离他最近的那个

即 SA [ rank [ i - 1] ]  - 1

也就是 , h [ i ] >= h [ i - 1 ] - 1

证毕

  

  所以我们每次找最长前缀的时候,都可以从 h [ i - 1 ]  开始检索

可以类比 manacher

代码如下:

void GetHeight() {
    int j, k = 0;
    for(int i = 1; i <= N; i++) {
        if(k) k--;
        int j = sa[rak[i] - 1];
        while(s[i + k] == s[j + k]) k++;
        Height[rak[i]] = k;
        printf("%d\n", k);
    }
}


题目:

【SDOI 2008】 Sandy的卡片

  

原文地址:https://www.cnblogs.com/rentu/p/11338901.html

时间: 2024-10-13 11:22:24

算法学习:后缀数组 height的求取的相关文章

POJ 3882 Stammering Aliens 后缀数组height应用

题目来源:POJ 3882 Stammering Aliens 题意:给你m一个一个字符串 求至少出现m次的最长字符串 可以在字符串中重叠出现 思路:二分长度l 然后从height数组中找长度大于等于l的前缀 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 40010; char s[maxn]; int sa[maxn]; i

算法学习 - 后缀表达式 (C++ 栈实现)

后缀表达式就是把一个式子进行树的后序遍历.然后根据这个顺序来求值. 栈来实现的时候很简单. 例如中缀表达式:6 * [ 5 + ( 2 + 3 )  * 8 + 3 ] 则 后缀表达式为:6 5 2 3 + 8 * + 3 + * 下面上代码: // // main.cpp // postfixExpression // // Created by Alps on 14-7-28. // Copyright (c) 2014年 chen. All rights reserved. // #inc

acdream 1430 SETI 后缀数组+height分组

这题昨天比赛的时候逗了,后缀想不出来,因为n^2的T了,就没往后缀数组想--而且之后解题的人又说用二分套二分来做,然后就更不会了-- 刚才看了题解,唉--原来题解说n^2的也可以过,然后就--这样了! #pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cstring> #include<algo

POJ - 1743 后缀数组 height分组

题意:求最长不可重叠的相同差值子串的长度 这道题算是拖了好几个月,现在花了点时间应该搞懂了不少,尝试分析一下 我们首先来解决一个退化的版本,求最长不可重叠的相同子串(差值为0) 比如\(aabaabaa\), 那么所求的子串有\(aab,aba,baa\)三个 如何求?不妨枚举.枚举是否有长度为\(k\)的最长不可重叠相同子串 可是后缀数组中并不能直接表示出子串,只能间接地用后缀来表示 长度为\(k\)的相同子串\(=>\)最大公共前缀长度为\(k\)的子串\(=>\)最大公共前缀长度大于等于

利用后缀数组(suffix array)求最长公共子串(longest common substring)

摘要:本文讨论了最长公共子串的的相关算法的时间复杂度,然后在后缀数组的基础上提出了一个时间复杂度为o(n^2*logn),空间复杂度为o(n)的算法.该算法虽然不及动态规划和后缀树算法的复杂度低,但其重要的优势在于可以编码简单,代码易于理解,适合快速实现. 首先,来说明一下,LCS通常指的是公共最长子序列(Longest Common Subsequence,名称来源参见<算法导论>原书第3版p223),而不是公共最长子串(也称为最长公共子串). 最长公共子串问题是在文本串.模式串中寻找共有的

POJ 题目3415 Common Substrings(后缀数组+栈,求可以匹配到的长度大于k的公共子串个数)

Common Substrings Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 8471   Accepted: 2798 Description A substring of a string T is defined as: T(i, k)=TiTi+1...Ti+k-1, 1≤i≤i+k-1≤|T|. Given two strings A, B and one integer K, we define S, a

字符串(马拉车算法,后缀数组,稀疏表):BZOJ 3676 [Apio2014]回文串

Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行,为一个只包含小写字母(a -z)的非空字符串s. Output 输出一个整数,为逝查回文子串的最大出现值. Sample Input [样例输入l] abacaba [样例输入2] www Sample Output [样例输出l] 7 [样例输出2] 4 HINT 一个串是回文的,当且仅当它从左

【算法学习笔记】36.凸包 求最大两点距离 SJTU OJ 1244 Date A Live

Description 某助教有好多好多妹纸,其中不乏来自五道口与东川路等男子职业技术学校的.然而,遥远的距离让他不得不花费大量的时间奔波于众多城市之间.为了更好地安排自己的约会计划,他想知道最远的两只妹纸之间的距离是多少. Input Format 第一行有一个整数n,表示妹纸的数量. 接下来n行,每行两个实数x,y,表示妹纸的坐标(假定在一个平面直角坐标系上). 对于80%的数据,n<=2000 对于90%的数据,n<=10000 对于100%的数据,n<=100000 Output

POJ 题目 3693 Maximum repetition substring(后缀数组+RMQ+枚举求最小字典序的重复次数最多的子串)

Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8067   Accepted: 2463 Description The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same conse