问题 A: 最长公共子序列问题(LCS)之备忘录法
题目描述
使用备忘录法求解两个序列的最长公共子序列的长度。
输入
每组输入包括两行,每行包括一个字符串。
输出
两个序列的最长公共子序列的长度。
样例输入 Copy
ACBCDABD ABDCABA
样例输出 Copy
5
def LCS(s1, s2, m, n, memo):
# 边界条件
if m == 0 or n == 0:
return 0
# 检查备忘录
if (m, n) in memo:
return memo[(m, n)]
# 递归计算
if s1[m-1] == s2[n-1]:
memo[(m, n)] = 1 + LCS(s1, s2, m-1, n-1, memo)
else:
memo[(m, n)] = max(LCS(s1, s2, m-1, n, memo), LCS(s1, s2, m, n-1, memo))
return memo[(m, n)]
while 1:
s1 = input()
s2 = input()
memo = {}
print(LCS(s1, s2, len(s1), len(s2), memo))
问题 B: 最长公共子序列问题(LCS)之动态规划法
题目描述
使用动态规划算法求解两个序列的最长公共子序列的长度。
输入
每组输入包括两行,每行包括一个字符串。
输出
两个序列的最长公共子序列的长度。
样例输入 Copy
ACBCDABD ABDCABA
样例输出 Copy
5
def LCS(X, Y):
len_X, len_Y = len(X), len(Y)
# 初始化dp数组
dp = [[0] * (len_Y + 1) for _ in range(len_X + 1)]
# 填充dp数组
for i in range(1, len_X + 1):
for j in range(1, len_Y + 1):
if X[i - 1] == Y[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
# 返回最长公共子序列的长度
return dp[len_X][len_Y]
while 1:
X = input()
Y = input()
print(LCS(X, Y))
问题 C: 最长公共子序列问题(LCS)-构造LCS
题目描述
使用动态规划算法求两个序列的最长公共子序列,需构造一条最长公共子序列。
输入
每组输入包括两行,每行包括一个字符串。
输出
两个字符序列的一条最长公共子序列。(输入已确保最长公共子序列的唯一性)
样例输入 Copy
acdbxx ccdxx
样例输出 Copy
cdxx
def LCS(X, Y):
len_X, len_Y = len(X), len(Y)
# 初始化DP表
dp = [["" for _ in range(len_Y + 1)] for _ in range(len_X + 1)]
# 填充DP表
for i in range(1, len_X + 1):
for j in range(1, len_Y + 1):
if X[i - 1] == Y[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + X[i - 1]
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1], key=len)
# 回溯找到最长公共子序列
lcs = ""
i, j = len_X, len_Y
while i > 0 and j > 0:
if X[i - 1] == Y[j - 1]:
lcs = X[i - 1] + lcs
i -= 1
j -= 1
elif len(dp[i - 1][j]) > len(dp[i][j - 1]):
i -= 1
else:
j -= 1
return lcs
while 1:
X = input()
Y = input()
print(LCS(X, Y))
问题 D: 牛牛的字符串
题目描述
牛牛有两个字符串(可能包含空格),他想找出其中最长的公共连续子串的长度,希望你能帮助他。例如:两个字符串分别为"abede"和"abgde",结果为2。
输入
每组数据包括两行,每行为一个字符串。
输出
输出最长的公共连续子串的长度。
样例输入 Copy
abede abgde
样例输出 Copy
2
def longest_common_substring(str1, str2):
len_str1, len_str2 = len(str1), len(str2)
# 初始化DP表
dp = [[0] * (len_str2 + 1) for _ in range(len_str1 + 1)]
max_length = 0 # 记录最长公共子串的长度
# 填充DP表
for i in range(1, len_str1 + 1):
for j in range(1, len_str2 + 1):
if str1[i - 1] == str2[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
max_length = max(max_length, dp[i][j])
else:
dp[i][j] = 0
return max_length
while 1:
str1 = input()
str2 = input()
print(longest_common_substring(str1, str2))
问题 E: 最大子段和
题目描述
给定n个整数(可能是负数)组成的序列a[1], a[2], a[3], …, a[n],求该序列的子段和如a[i]+a[i+1]+…+a[j]的最大值。
输入
每组输入包括两行,第一行为序列长度n,第二行为序列。
输出
输出字段和的最大值。
样例输入 Copy
5 -1 0 1 2 3
样例输出 Copy
6
def max_subarray_sum(a):
n = len(a)
# 初始化dp数组
dp = [0] * n
dp[0] = a[0]
max_sum = dp[0] # 记录最大子段和
# 填充dp数组
for i in range(1, n):
dp[i] = max(dp[i - 1] + a[i], a[i])
max_sum = max(max_sum, dp[i])
return max_sum
while 1:
n = int(input())
a = list(map(int, input().split()))
print(max_subarray_sum(a))
问题 F: 最大子段和升级版
题目描述
使用动态规划算法求整数数组(可能包含负整数)的最大子段和,以及和最大子段的起始位置和结束位置:
例如:输入数组(6,-1,5,4,-7),输出14, 1, 4,其中14表示最大子段和,1表示和最大的子段从第1个数字开始,4表示和最大的子段到第4个数字结束,即(6, -1 , 5, 4)。
输入
每组输入两行,第1行为数组中包含的整数个数n,第2行为n个整数(可能包含负整数),两两之间用空格隔开。
输出
输出最大子段和,以及和最大子段的起始位置和结束位置,两两之间用空格隔开。
样例输入 Copy
5 6 -1 5 4 -7
样例输出 Copy
14 1 4
def solve(a, n):
b = [0] * n
b[0] = a[0]
max_sum = b[0]
start = end = 0
for i in range(1, n):
if b[i - 1] > 0:
b[i] = b[i - 1] + a[i]
else:
b[i] = a[i]
if max_sum < b[i]:
max_sum = b[i]
end = i
# 找到最大子段和的起始位置
j = end
while b[j] > 0 and j >= 0:
j -= 1
start = j + 1 # 根据题目要求,起始位置从1开始计数
# 输出最大子段和,起始位置和结束位置
print(max_sum, start + 1, end + 1) # 加1是因为题目要求的位置是从1开始计数
n = int(input())
while n != -1:
a = list(map(int, input().split()))
solve(a, n)
n = int(input())