📌  相关文章
📜  分割给定二进制字符串的最低成本(1)

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

以'分割给定二进制字符串的最低成本'作主题

介绍

给定一个由0和1组成的二进制字符串,将该字符串分割成多个非空子串,使每个子串都是由相同的字符组成的,对于每个子串,计算其成本,成本为串中0或1的数量(因为子串都是相同字符组成的,所以非简单子串的成本为0),求所有子串成本之和的最小值。

举个例子,输入字符串"11011000",最低成本分割方案为:"110","110","00",每个子串的成本为2,0,2,总成本为4。

思路

要分割成多个非空子串,让它们尽可能地相似。
我们可以从左到右遍历字符串,记录当前字符和出现的次数。说明当前字符出现的次数cnt大于前面不同的字符个数即表明开始一个新的子串,否则继续加入当前子串。
由于要尽量分割成相似的,我们可以采用动态规划,dp[i]表示0~i的字符串的最低成本。
遍历到第i个位置时,将字符串分成从j~i子串和从j+1~i子串。
其中j从0~i-1遍历,当当前子串所含字符相同时,转移方程为dp[i]=min(dp[i], dp[j]+cost[j+1][i]),其中cost[j+1][i]表示从j+1到i这个子串的成本。
最后返回dp[n-1]即为结果。

代码
def minCost(s: str) -> int:
    n = len(s)
    cost = [[0] * n for _ in range(n)]
    for i in range(n):
        for j in range(i, n):
            cnt = s[j : i + 1].count("0")
            cost[i][j] = cnt if cnt == 0 or cnt == i - j + 1 else cnt
    dp = [0] * n
    for i in range(n):
        dp[i] = cost[0][i]
        for j in range(i):
            if s[i] == s[j]:
                dp[i] = min(dp[i], dp[j] + cost[j + 1][i])
    return dp[n - 1]

代码片段中,cost[i][j]表示从j到i的子串的成本,dp[i]表示0~i的字符串的最低成本,转移方程见上。