📅  最后修改于: 2023-12-03 15:23:37.251000             🧑  作者: Mango
给定一个字符串,需要将其分成三个子字符串。要求分割后的子字符串长度分别为 $a, b, c$,且 $a \leq b \leq c$。请你在满足上述条件的前提下,删除尽可能少的字符,使得原字符串可以被分成三个满足要求的子字符串。
对于字符串 $s$,我们可以从左到右遍历字符串,设当前处理的位置为 $i$,我们枚举第二个子字符串的结束位置 $j$ 和第三个子字符串的结束位置 $k$,我们需要满足下面的两个条件:
设 $s1$ 为前 $i$ 个字符组成的子串,$s2$ 为第 $i+1$ 到 $j$ 个字符组成的子串,$s3$ 为第 $j+1$ 到 $k$ 个字符组成的子串,$s4$ 为第 $k+1$ 到 $n$ 个字符组成的子串,可以得到下面这个等式:
$$a + b + c + d = n,\quad i < j < k$$
要使得删除的字符最少,我们需要尽可能地让第二个子字符串和第三个子字符串的长度尽可能地大,即 $b$ 和 $c$ 距离 $i$ 和 $j$ 的位置尽量远。
为了使得复杂度为 $O(n)$,我们可以先遍历一遍字符串,计算出 $i$ 和 $j$ 的所有情况下可能的最大值和最小值,然后对于每个 $i$ 和 $j$,计算出 $k$ 以及对应的 $c$ 和 $d$,最终取删除的字符数最少的方案。
我们先计算出 $i$ 和 $j$ 的上下界,然后枚举每个 $i$ 和 $j$,计算出 $k$ 和对应的 $c$ 和 $d$。时间复杂度为 $O(n)$。
def solve(s):
n = len(s)
INF = float("inf")
# 预处理出 i 和 j 的上下界
mi_j = [n]*n
mx_i, mi_i = -1, INF
for i in range(n):
if i > mx_i: mx_i = i
if s[i] < s[mx_i]: mx_i = i
if i < mi_i: mi_i = i
if mx_i - i > mi_j[mx_i]: mi_j[mx_i] = mx_i - i
if i - mi_i > mi_j[mx_i]: mi_j[mx_i] = i - mi_i
mx_j, mi_j = -1, INF
for j in range(n):
if j > mx_j: mx_j = j
if s[j] < s[mx_j]: mx_j = j
if j < mi_j: mi_j = j
if mx_j - j > mi_j: mi_j = mx_j - j
if j - mi_j > mi_j: mi_j = j - mi_j
ans = INF
for i in range(n):
for j in range(i + 1, n):
if j - i > mi_j[j]: continue
if n - j > mi_j[n - 1]: continue
k = j + 1
while k < n and s[k] <= s[i] and (k - j <= mi_j[j]) and (n - k <= mi_j[n - 1]):
k += 1
if k == n: continue
ans = min(ans, n - (k + 1))
return ans
本问题可以通过预处理出 $i$ 和 $j$ 的上下界,并枚举每个 $i$ 和 $j$,计算出 $k$ 和对应的 $c$ 和 $d$ 来解决。复杂度为 $O(n)$。