📌  相关文章
📜  最小 K 使得每个长度至少为 K 的子串都包含一个字符c |第 2 组(1)

📅  最后修改于: 2023-12-03 14:55:20.086000             🧑  作者: Mango

求解最小K使得每个长度至少为K的子串都包含一个字符c

在本题中,我们需要找到一个最小的K,使得给定的字符串中,每个长度至少为K的子串都包含字符c。例如,对于字符串"abcdbccc"和字符c='c',最小的K为3,因为"bcc"是长度为3的子串且含有字符c。

解法一:暴力枚举

对于一个长度为n的字符串,我们可以暴力枚举所有长度大于等于K的子串,并判断每个子串是否包含字符c。时间复杂度为O(n^2K)。

def min_k(s, c):
    n = len(s)
    for k in range(1, n + 1):
        for i in range(n - k + 1):
            if c not in s[i:i+k]:
                break
        else:
            return k
    return -1
解法二:二分答案

我们可以通过二分答案来优化时间复杂度。假设当前二分到的K为mid,我们可以使用滑动窗口来判断是否存在长度至少为mid的子串不包含字符c。具体来说,我们维护一个滑动窗口,使得窗口内的子串长度恰好为mid,然后移动窗口,判断窗口内是否包含字符c。时间复杂度为O(nlogn)。

def has_substring(s, c, k):
    n = len(s)
    freq = [0] * 26
    for i in range(k):
        freq[ord(s[i]) - ord('a')] += 1
    for i in range(k, n):
        if freq[ord(c) - ord('a')] > 0:
            return True
        freq[ord(s[i-k]) - ord('a')] -= 1
        freq[ord(s[i]) - ord('a')] += 1
    return freq[ord(c) - ord('a')] > 0

def min_k(s, c):
    n = len(s)
    l, r = 1, n
    ans = -1
    while l <= r:
        mid = (l + r) // 2
        if has_substring(s, c, mid):
            ans = mid
            r = mid - 1
        else:
            l = mid + 1
    return ans
总结

本题可以通过枚举和二分答案来求解。通过二分答案可以将时间复杂度从O(n^2K)降低到O(nlogn)。