📌  相关文章
📜  在二进制字符串的任何循环中的开头和结尾连续放置的最大 0 数(1)

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

在二进制字符串的任何循环中的开头和结尾连续放置的最大 0 数

二进制字符串是由0和1组成的字符串。一个二进制字符串的循环是通过循环移位将原字符串的一个字串放置于字符串的末尾得到的。

在任意长度的二进制字符串的循环中,可能出现开头和结尾连续放置的0,本文将介绍如何求出这样的最大0数。

解法一:暴力枚举

对于每一个长度不大于原字符串长度一半的字串,检查该字串是否符合开头和结尾连续放置的0的条件,取其中最大的数即可。

时间复杂度为 $O(n^2)$,无法通过本题。

代码片段:

def max_consecutive_zeroes(s: str) -> int:
    n = len(s)
    ans = 0
    for i in range(n):
        for j in range(1, n // 2 + 1):
            if s[i:i+j] == '0'*j and s[i-j:i] == s[n-j-i:n-i]:
                ans = max(ans, j)
    return ans
解法二:KMP算法

本题可以用KMP算法求解,KMP算法的本质是利用已匹配的信息来避免无效的重新匹配。

我们将原字符串复制一遍得到一个新的字符串 $ss$,这样任何一个在原字符串中循环得到的字符串一定是在 $ss$ 中的一个连续子串。

在 $ss$ 中查找最长的开头和结尾连续放置的0的字串,以该字串的长度为$t$,那么原字符串中任何一个长度大于等于$t$的连续循环中,一定都存在开头和结尾连续放置的0且最多有$t$个0。

时间复杂度为 $O(n)$。

代码片段:

def max_consecutive_zeroes(s: str) -> int:
    # 构造新字符串
    ss = s + s
    # 计算next数组
    n = len(ss)
    next = [0] * (n + 1)
    next[0] = -1
    i, j = 0, -1
    while i < n:
        if j == -1 or ss[i] == ss[j]:
            i, j = i + 1, j + 1
            next[i] = j
        else:
            j = next[j]
    # 查找包含末尾的0的最长前缀字串
    t = n - next[n]
    # 查找包含开头的0的最长后缀字串
    for i in range(n - t, n):
        if ss[i:i+t] != '0' * t:
            t -= 1
            break
    return t

以上是本题的两种解法,其中解法二的KMP算法是更好的解法。