📜  索引范围内回文子串的计数(1)

📅  最后修改于: 2023-12-03 15:41:11.352000             🧑  作者: Mango

索引范围内回文子串的计数

在计算机科学中,回文串是一个正着和反着读都一样的字符串。题目要求我们计算给定字符串中在给定索引范围内所有回文子串的个数。

解法
暴力法

最简单直接的想法是枚举所有子串,再判断该子串是否为回文串。但是这种方法的时间复杂度为$O(n^3)$,在实际应用中当$n\gt10^3$时,已经无法承受。

中心扩展法

回文中心可以是一个字符或者两个字符组成的。我们可以从左到右枚举回文中心的位置,然后尝试扩展得到回文串,并统计答案。时间复杂度为$O(n^2)$,是一种比较优秀的解法。

def countSubstrings(s: str, left: int, right: int) -> int:
    ans = 0
    # 枚举回文中心
    for i in range(left, right+1):
        # 回文中心为一个字符
        l, r = i, i
        while l >= left and r <= right and s[l] == s[r]:
            ans += 1
            l -= 1
            r += 1
        # 回文中心为两个字符
        l, r = i, i+1
        while l >= left and r <= right and s[l] == s[r]:
            ans += 1
            l -= 1
            r += 1
    return ans
Manacher法

Manacher算法是一种将时间复杂度降至$O(n)$的算法。它的基本思想是在求解回文串时,利用已有的信息,避免了重复计算。具体可以参考Manacher算法详解

def countSubstrings(s: str, left: int, right: int) -> int:
    t = ['$', '#']
    for c in s:
        t.append(c)
        t.append('#')
    r, c, ans = [0] * len(t), 0, 0
    for i in range(1, len(t)):
        if i < r[c]:
            r[i] = min(r[2*c-i], r[c]-i+r[c])
        else:
            r[i] = 1
        while i-r[i] >= 0 and i+r[i] < len(t) and t[i-r[i]] == t[i+r[i]]:
            r[i] += 1
        if i+r[i] > r[c]:
            c = i
        if i >= 2*left and i <= 2*right:
            ans += (r[i] - 1) // 2
    return ans
总结

中心扩展法相对来说比较简单易懂,而Manacher算法虽然复杂,但是速度非常快。在实际应用中,可以根据需要选择不同的算法。