📌  相关文章
📜  计算所有子串的字符权重不超过K(1)

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

计算所有子串的字符权重不超过K

问题

给定一个字符串和一个整数K,求出所有的子串中,字符权重之和不超过K的子串个数。

字符权重指的是字符在字符串中出现的次数。

例如,对于字符串"aaabbc",其子串"aa"的字符权重为2,子串"ab"的字符权重为1。

思路

我们可以枚举所有的子串,然后计算其字符权重,并统计所有符合条件的子串的数量。

对于计算字符权重,我们可以使用一个map来保存每个字符出现的次数,然后累加每个字符的出现次数即可。

我们可以通过滑动窗口来遍历所有的子串,并在遍历的过程中,动态地更新累计的字符权重信息。

具体来说,我们可以使用两个指针left和right,分别表示当前滑动窗口的左右边界。我们从左向右遍历字符串,并移动right指针,每次将right指向的字符的出现次数加1,然后更新当前滑动窗口中的字符权重。

如果当前字符权重超过了K,那么我们就需要移动left指针,同时将left指向的字符的出现次数减1。这样可以保证滑动窗口中的字符权重和不超过K。

当我们移动left指针时,有一个特殊情况需要注意,即如果当前left指针指向的字符在滑动窗口中已经不存在了,那么我们就需要从map中将其删除。

具体实现可以参考下面的代码片段。

代码
def count_substrings(s: str, k: int) -> int:
    n = len(s)
    cnt = {}
    left, right = 0, 0
    res = 0
    while right < n:
        # move right pointer and update character count
        cnt[s[right]] = cnt.get(s[right], 0) + 1
        # update substring weight
        weight = sum(cnt.values())
        # move left pointer if weight is too big
        while weight > k and left <= right:
            cnt[s[left]] -= 1
            if cnt[s[left]] == 0:
                del cnt[s[left]]
            left += 1
            weight = sum(cnt.values())
        # count valid substrings ending with s[right]
        if weight <= k:
            res += right - left + 1
        right += 1
    return res
复杂度

时间复杂度:$O(n^2)$

空间复杂度:$O(n)$

其中n为字符串s的长度。