LC 3261. 统计满足 K 约束的子字符串数量 II

https://leetcode.cn/problems/count-substrings-that-satisfy-k-constraint-ii/description/

这题想了挺久的,有好几个点都是慢慢想到的:

class Solution:
    def countKConstraintSubstrings(self, s: str, k: int, queries: List[List[int]]) -> List[int]:
        n = len(s)

        def build_end():
            a, b = n, n
            right = [n] * (n + 1)
            for i in reversed(range(n)):
                if s[i] == '0':
                    right[i] = a
                    a = i
                else:
                    right[i] = b
                    b = i
            a, b = n, n
            for i in range(n):
                if s[i] == '0':
                    a = i
                    break
            for i in range(n):
                if s[i] == '1':
                    b = i
                    break
            for _ in range(k):
                a = right[a]
                b = right[b]

            end = [-1] * n
            for i in range(n):
                end[i] = max(a, b)
                if s[i] == '0':
                    a = right[a]
                else:
                    b = right[b]
            return end

        end = build_end()

        def search(x):
            s, e = 0, n - 1
            while s <= e:
                m = (s + e) // 2
                if end[m] <= x:
                    s = m + 1
                else:
                    e = m - 1
            return e

        acc = [0] * (n + 1)
        for i in range(n):
            acc[i + 1] = acc[i] + (end[i] - i)

        # print(end)
        ans = []
        for a, b in queries:
            p = search(b + 1)
            r = 0
            # [a...p]
            # where end[p] <= (b+1)
            if p >= a:
                r += acc[p + 1] - acc[a]
            else:
                p = a - 1

            # [p + 1 .. end + 1]
            # [p + 2 .. end + 1]
            # [end + 1.. end + 1]
            sz = (b + 1 - p)
            r += (b - p) * sz - (sz - 1) * sz // 2
            ans.append(r)

        return ans