具有O(N)复杂度的字符串中回文切片的数量

时间:2018-05-31 09:29:11

标签: python algorithm

def solution(S):
    total = 0
    i = 1
    while i <= len(S):
        for j in range(0, len(S) - i + 1):
            if is_p(S[ j: j + i]):
                total += 1
        i += 1
    return total

def is_p(S):
    if len(S) == 1:
        return False
    elif S == S[::-1]:
        return True
    else:
        return False

我正在编写一个函数来计算字符串中回文切片(长度大于1)的数量。上面的代码时间复杂度很低。有人可以帮助我改进它并使其具有O(N)复杂性吗?

编辑:这不是重复,因为另一个问题是关于寻找最长的回文切片

2 个答案:

答案 0 :(得分:0)

这可以使用后缀树在线性时间内完成:

1)对于常量字母表,我们可以使用U(n)中的Ukkonen算法构建后缀树。

2)对于给定的字符串S,构建S#S'的通用后缀树,其中S'与字符串S相反,#是分隔字符。

3)现在在这个后缀树中,对于S中的每个后缀i,寻找(2n-i + 1)后缀的最低共同祖先是S'。

4)计算树中所有这些后缀的数量,以获得所有回文的总数。

答案 1 :(得分:0)

应用Manacher's Algorithm,同样由multiple answers to this question描述。

它为您提供以每个位置为中心的最长回文的长度(以奇数长度为中心,或以偶数长度为中心)。您可以使用它来轻松计算回文的数量。请注意,每个回文必须位于某处的中心位置,因此它必须是以中心为中心的最长回文的子串(或等于)。

因此请考虑字符串ababcdcbaa。通过Manacher算法,您知道以d为中心的最大长度回文长度为7:abcdcba。根据回文的属性,您立即知道bcdcbcdc以及d也是以d为中心的回文。事实上,如果你知道那里居中的最长回文的长度为floor((k+1)/2),那么k回文就会集中在一个位置。

因此,您总结了Manacher算法的结果,以计算所有回文数。如果您只想计算长度为> 1的回文,您只需要减去长度为1的回文数,这只是n,即字符串的长度。