【问题标题】:How can I find the occurence number of each suffix in a string?如何找到字符串中每个后缀的出现次数?
【发布时间】:2017-02-24 12:53:38
【问题描述】:

我想在 O(nlogn) 或 O(n) 时间内找出字符串的每个后缀在 原始 字符串中出现的次数。

例如字符串aba,后缀a出现两次,ba出现一次,aba出现一次。

【问题讨论】:

  • 我读过 :) 我哪里错了?
  • 你需要问一个关于算法或一段代码的具体问题,而不仅仅是“我如何做到这一切”。
  • 我只是要求一个算法...我的意思是,我如何输入一个字符串,并输出 O(nlogn) 中每个后缀的出现次数。不是很具体吗?我不会关注代码的细节,只需要一个算法。
  • @newbie 后缀a 如何出现两次?我认为这里的总后缀是 3:a. ba. aba

标签: c++ string algorithm hash suffix-array


【解决方案1】:

后缀数组解决方案

构造字符串 S 的后缀树以及 LCP 数组。这将有助于计算每个后缀的所有出现次数。

不了解后缀数组和LCP是什么,很难理解。

suffix array

LCP

kasai’s Algorithm for Construction of LCP array from Suffix Array

让我们举一个例子字符串并创建它的后缀数组。考虑字符串 S = "ABABBAABB"。

suffix positions(pos)   Suffixes of S   LCP array of S
    5                   AABB            1
    0                   ABABBAABB       2
    6                   ABB             3
    2                   ABBAABB         0
    8                   B               1
    4                   BAABB           2
    1                   BABBAABB        1
    3                   BBAABB          2
    7                   BB              not Defined

First column(pos array)是Suffix Array中排序后缀的原始起点。我们将第二列称为 SuffixArray(我们不需要计算它,它只是为了可视化)。

现在,我们知道 LCP[i]= SuffixArray[i] 和 SuffixArray[i+1] 之间的最长公共前缀的长度。例如LCP1=lcp("ABABBAABB","ABB")=2.

令 Count[i] = 后缀从位置 i 开始出现的次数。

for (int i = 0; i < n; )
{
    int j=i;
    while(LCP[j]==n-pos[j]){ // loop if SuffixArray[j] is a prefix of SuffixArray[j+1] 
        j++;
    }
    int incr=1;
    for (int k = j-1; k>= i ; --k)
    {
        count[ pos[k] ] = incr;
        incr++;
    } 
    i=j+1;
}

这是高度优化的解决方案,如果您仔细观察所有步骤,复杂度为 O(n log n)

希望对您有所帮助。如果您第一次尝试不明白,请重新检查所有内容。



编辑: 这个计数数组的计算有一个小错误。基本上我的问题是在 LCP 数组中找到小于当前值的下一个索引.我正在提供正确的实现。

stack< int > stack;

count[ pos[n-1] ] = 1;

for(int i=n-2;i>=0;i--){
    while(!stack.empty() and LCP[stack.top()]>=LCS[i]){
        stack.pop();
    }

    if( LCP[i] == n-pos[i]  ){
        if (stack.empty())
        {
            count[ pos[i] ] = n-i ;
        }else{
            count[ pos[i] ] = stack.top()-i ;
        }

    }else{
        count[ pos[i] ] = 1;
    }

    stack.push(i);

}

next smaller element in array


【讨论】:

  • 在你的编辑中 k 应该是 i 吗?是计算大小为 n 的一维数组吗?
猜你喜欢
  • 2014-08-31
  • 1970-01-01
  • 1970-01-01
  • 2021-06-24
  • 2014-12-12
  • 1970-01-01
  • 1970-01-01
  • 2022-10-15
  • 1970-01-01
相关资源
最近更新 更多