最长公共前缀属性

时间:2013-04-21 05:57:02

标签: string algorithm

我正在通过后缀数组及其用于计算两个后缀的最长公共前缀。

消息来源说:

  

“两个后缀之间的lcp是数组中它们之间所有相邻后缀对的lcp的最小值”

即。 lcp(x,y)=min{ lcp(x,x+1),lcp(x+1,x+2),.....,lcp(y-1,y) } 其中x和y是字符串的两个索引开始的字符串的两个索引。

我不相信字符串"abca"的例子中的陈述。

lcp(1,4)=1(考虑基于1的索引)

但如果我应用上面的等式,那么

lcp(1,4)=min{lcp(1,2),lcp(2,3),lcp(3,4)}

我认为lcp(1,2)=0

所以答案必须是0根据等式。

我在某处弄错了吗?

2 个答案:

答案 0 :(得分:2)

我认为源引用的索引不是字符串本身的索引,而是排序后缀的索引。

a
abca
bca
ca

因此

lcp(1,2) = lcp(a, abca) = 1
lcp(1,4) = min(lcp(1,2), lcp(2,3), lcp(3,4)) = 0

答案 1 :(得分:0)

你不能通过简单地计算阵列中它们之间所有相邻后缀对的lcp的最小值来找到任何两个后缀的LCP。

我们可以计算任何后缀(i,j)的LCP 在以下帮助下:

LCP(suffix i,suffix j)=LCP[RMQ(i + 1; j)]  

另请注意(i<j) LCP (suff i,suff j)可能不一定等于LCP (Suff j,suff i)。 RMQ 范围最小查询

paper的第3页。

Details:

第1步: 首先计算邻接/连续后缀对的LCP。

n =字符串的长度。

suffixArray []是后缀数组。

void calculateadjacentsuffixes(int n)
{
    for (int i=0; i<n; ++i) Rank[suffixArray[i]] = i;
    Height[0] = 0;
    for (int i=0, h=0; i<n; ++i)
    {
        if (Rank[i] > 0)
        {
            int j = suffixArray[Rank[i]-1];
            while (i + h < n && j + h < n && str[i+h] == str[j+h])
            {
                h++;
            }
            Height[Rank[i]] = h;
            if (h > 0) h--;
        }
    }
}

注意:高度[i] = LCPs(后缀i-1,后缀i)即。高度数组包含相邻后缀的LCP。

第2步:

使用RMQ概念计算任意两个后缀i,j的LCP。  RMQ预计算功能:

void preprocesses(int N)
{
    int i, j;

    //initialize M for the intervals with length 1
    for (i = 0; i < N; i++)
        M[i][0] = i;

    //compute values from smaller to bigger intervals
    for (j = 1; 1 << j <= N; j++)
    {
        for (i = 0; i + (1 << j) - 1 < N; i++)
        {
            if (Height[M[i][j - 1]] < Height[M[i + (1 << (j - 1))][j - 1]])
            {
                M[i][j] = M[i][j - 1];
            }
            else
            {
                M[i][j] = M[i + (1 << (j - 1))][j - 1];
            }
        }
    }
}  

步骤3:计算任意两个后缀i,j之间的LCP

int LCP(int i,int j)
{
    /*Make sure we send i<j always */
    /* By doing this ,it resolve following
    suppose ,we send LCP(5,4) then it converts it to LCP(4,5)
    */
    if(i>j)
        swap(i,j);

    /*conformation over*/

    if(i==j)
    {
        return (Length_of_str-suffixArray[i]);
    }
    else
    {
        return Height[RMQ(i+1,j)];
        //LCP(suffix i,suffix j)=LCPadj[RMQ(i + 1; j)] 
        //LCPadj=LCP of adjacent suffix =Height.
    }
}

RMQ功能是:

int RMQ(int i,int j)
{
    int k=log((double)(j-i+1))/log((double)2);
    int vv= j-(1<<k)+1 ;
    if(Height[M[i][k]]<=Height[ M[vv][ k] ])
        return M[i][k];
    else
        return M[ vv ][ k];
}

请参阅 Topcoder tutorials 获取RMQ。

您可以在我的 blog 中查看C ++中的完整实现。