数学题-6251. 统计回文子序列数目

1930. 长度为 3 的不同回文子序列

问题描述

给你一个字符串 s ,返回 s 中 长度为 3 的不同回文子序列 的个数。

即便存在多种方法来构建相同的子序列,但相同的子序列只计数一次。

回文 是正着读和反着读一样的字符串。

子序列 是由原字符串删除其中部分字符(也可以不删除)且不改变剩余字符之间相对顺序形成的一个新字符串。

例如,"ace" 是 "abcde" 的一个子序列。

示例 1:

输入:s = "aabca"
输出:3
解释:长度为 3 的 3 个回文子序列分别是:

  • "aba" ("aabca" 的子序列)
  • "aaa" ("aabca" 的子序列)
  • "aca" ("aabca" 的子序列)
    示例 2:

输入:s = "adc"
输出:0
解释:"adc" 不存在长度为 3 的回文子序列。
示例 3:

输入:s = "bbcbaba"
输出:4
解释:长度为 3 的 4 个回文子序列分别是:

  • "bbb" ("bbcbaba" 的子序列)
  • "bcb" ("bbcbaba" 的子序列)
  • "bab" ("bbcbaba" 的子序列)
  • "aba" ("bbcbaba" 的子序列)

提示:

3 <= s.length <= 105
s 仅由小写英文字母组成

问题求解

提前记录一下数字即可。

class Solution:
    def countPalindromicSubsequence(self, s: str) -> int:
        n = len(s)
        res = 0
        freq = Counter(s)
        record = defaultdict(int)
        used = set()

        for i in range(n):
            for c in freq.keys():
                l = record[c]
                r = freq[c] - record[c] if c != s[i] else freq[c] - record[c] - 1
                if l and r and s[i] + c not in used: 
                    used.add(s[i] + c)
                    res += 1
            record[s[i]] += 1
        
        return res

6251. 统计回文子序列数目

问题描述

给你数字字符串 s ,请你返回 s 中长度为 5 的 回文子序列 数目。由于答案可能很大,请你将答案对 109 + 7 取余 后返回。

提示:

如果一个字符串从前往后和从后往前读相同,那么它是 回文字符串 。
子序列是一个字符串中删除若干个字符后,不改变字符顺序,剩余字符构成的字符串。

示例 1:

输入:s = "103301"
输出:2
解释:
总共有 6 长度为 5 的子序列:"10330" ,"10331" ,"10301" ,"10301" ,"13301" ,"03301" 。
它们中有两个(都是 "10301")是回文的。
示例 2:

输入:s = "0000000"
输出:21
解释:所有 21 个长度为 5 的子序列都是 "00000" ,都是回文的。
示例 3:

输入:s = "9999900000"
输出:2
解释:仅有的两个回文子序列是 "99999" 和 "00000" 。

提示:

1 <= s.length <= 104
s 只包含数字字符。

问题求解

需要特别注意的是由于字符集的有限性,因此可以将两两配对的所有个数存储下来。

class Solution:
    def countPalindromes(self, s: str) -> int:
        suf = [0] * 10
        suf2 = [0] * 100
        for d in map(int, s[::-1]):
            for i, c in enumerate(suf):
                suf2[d * 10 + i] += c
            suf[d] += 1
        
        res = 0
        pre = [0] * 10
        pre2 = [0] * 100
        for d in map(int, s):
            suf[d] -= 1
            for i, c in enumerate(suf):
                suf2[d * 10 + i] -= c
            res += sum(a * b for a, b in zip(suf2, pre2))
            for i, c in enumerate(pre):
                pre2[d * 10 + i] += c
            pre[d] += 1
        return res % (10 ** 9 + 7)
posted @ 2022-11-27 11:53  hyserendipity  阅读(44)  评论(0编辑  收藏  举报