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

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

  suffix[j] 和 suffix[k] 的最长公共前缀为 height[Rank[j]+1] , height[Rank[j]+2],......,height[Rank[k]] 中的最小值。

  例如,字符串为“aabaaaab”,求后缀“abaaaab”和后缀“aaab”的最长公共前缀,如图4所示:

 

  

  那么应该如何高效的求出height值呢?

  定义 h[i] = height[Rank[i]],也就是suffix(i)和它前一名的最长公共前缀。

  h数组有以下性质: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数组,只需按照h[1],h[2],h[3],...,h[n]的顺序计算即可。

  代码:

 

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

 

转载于:https://www.cnblogs.com/yongren1zu/p/3239270.html

### 关于NOI金牌导航中的字符串算法与后缀数组 在处理涉及多个字符串连接并构建其后缀数组的问题时,一种有效的方法是在这些字符串之间插入不同的分隔符[^1]。此方法确保了即使原始字符串内部存在重复部分,在计算后缀数组过程中仍能区分来自不同源字符串的部分。 对于具体实现而言,当面对需要高效查询和匹配的任务时,除了基本的后缀数组外,还可以考虑使用更高级的数据结构如广义SAM(Suffix Automaton),这有助于统计本质不同的子串数量以及其他复杂的模式识别操作[^3]。然而值得注意的是,并不是所有情况下都适合采用最复杂的数据结构;有时简单的基于后缀数组的操作已经能够满足需求,尤其是在时间复杂度要求较为严格的情况下——例如通过二分法配合后缀分组来解决问题可以达到\(O(n\log n)\)的时间效率。 针对特定应用场景下的性能优化也至关重要。某些场景下,尽管理论上可行的做法可能因为实际输入特性而表现不佳,比如高度随机化的Height数组可能导致较高复杂度算法超时(TLE),此时就需要根据具体情况调整策略以适应数据特点[^5]。 ```cpp // 示例代码:简单展示如何创建两个字符串之间的后缀数组 #include <iostream> #include <vector> #include <string> using namespace std; void build_suffix_array(const string &text, vector<int> &suffixArray){ int n = text.size(); suffixArray.resize(n); // 构造后缀数组逻辑... } int main(){ string s1="abc",s2="def"; char separator='#'; // 假设'#'不在任何给定字符串内出现 string combinedString=s1+separator+s2; vector<int> sa; build_suffix_array(combinedString,sa); cout << "Combined String with Separator: " << combinedString << endl; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值