周赛250915
时隔多日再才重新开启周赛。这场DP居多。
T2-3290. 最高乘法得分
题目大意:
给定两个数组 a
和 b
,数组 a
长度为 4,数组 b
长度至少为 4。需要从 b
中选择 4 个递增下标 i0 < i1 < i2 < i3
,计算 a[0] * b[i0] + a[1] * b[i1] + a[2] * b[i2] + a[3] * b[i3]
,并返回最大得分。
代码实现思路:
- 使用动态规划的思想解决问题。定义
f[i][j]
表示在前i
个元素中选择了j
个数时的最大得分。 - 初始化
f[0][0] = 0
,表示在没有元素的情况下选择 0 个数时得分为 0,其余情况初始化为负无穷大。 - 遍历数组
b
,对于每一个位置i
,我们可以选择保留当前状态(即不选第i
个元素,继承上一个状态的值),或者选择第i
个元素(更新当前状态,计算乘积并加到上一个状态f[i-1][j-1]
中)。 - 最后,结果就是从长度为
4
的选择中得到的最大得分max(f[i][4])
。
class Solution:
def maxScore(self, a: List[int], b: List[int]) -> int:
n = len(b)
f = [[-inf]*5 for _ in range(n + 1)] # f[i][j] 表示 b 中 前 i 个数字(不包括i)中选 j 个可以获得的最大得分
f[0][0] = 0
for i in range(1, n + 1):
for j in range(min(4, i) + 1):
f[i][j] = f[i-1][j]
if j:
f[i][j] = max(f[i][j], f[i-1][j-1] + a[j - 1] * b[i - 1])
return max(f[i][4] for i in range(4, n + 1))
T3&4-3291. 形成目标字符串需要的最少字符串数 I
题目大意:
给定一个字符串数组 words
和一个目标字符串 target
,需要通过连接 words
中的有效前缀字符串组成目标字符串 target
。要求计算连接有效字符串形成 target
所需的最少字符串数量。如果无法组成 target
,返回 -1。
代码实现思路:
- 使用 Z 函数 计算
words
中每个字符串与target
对应位置的最长匹配前缀,得到每个位置能匹配的最大长度nxt
数组。 - 动态规划数组
f[i]
表示到达target
的第i
个字符所需的最少字符串数量,初始时f[0] = 0
,表示到达初始位置需要 0 个字符串。 - 遍历
target
,如果某个位置无法通过前面的组合到达,则返回 -1;否则根据前面的匹配情况不断更新f
数组,记录当前能够延伸的最长有效前缀last
。 - 在遍历过程中,如果找到一个位置
i
,可以用更少的字符串覆盖更长的前缀,则更新f
数组和last
。 - 最后返回
f[n]
,即完整匹配target
所需的最少字符串数。
def z_function(s):
n = len(s)
z = [0] * n
l, r = 0, 0
for i in range(1, n):
if i<=r and z[i - l] < r - i + 1:
z[i] = z[i-l]
else:
z[i] = max(0, r - i + 1)
while i + z[i] < n and s[z[i]] == s[i + z[i]]:
z[i] += 1
if i + z[i] - 1 > r:
l, r = i, i + z[i] - 1
return z
class Solution:
def minValidStrings(self, words: List[str], target: str) -> int:
n = len(target)
nxt = [0] * n
for w in words:
s = w + '#' + target
z = z_function(s)
for i in range(n):
nxt[i] = max(nxt[i], z[i + len(w) + 1])
f = [-1] * (n + 1)
f[0] = 0
last = 0 # 所有 words 可以拓展到的target的最长长度
for i in range(n):
if f[i] == -1:
continue
if i > last:
return -1
nx = nxt[i]
if i + nx > last:
for j in range(last + 1, i + nx + 1):
f[j] = f[i] + 1
last = i + nx
if last == n:
break
return f[n]