设计动态规划算法,找到例题中的2条最长子序列的算法设计和建立的模型
时间: 2024-02-13 20:07:21 浏览: 103
首先,我们需要明确什么是最长子序列。最长子序列是指一个序列中的一段连续的子序列,使得该子序列中的元素在原序列中的相对顺序不变,并且该子序列的长度最大。
现在,我们来考虑如何设计动态规划算法来解决最长子序列问题。
假设我们有两个序列:A和B,它们的长度分别为m和n。我们定义一个二维数组dp,其中dp[i][j]表示A的前i个元素和B的前j个元素的最长公共子序列的长度。
我们可以采用如下的递推式来计算dp[i][j]的值:
当A[i] == B[j]时,dp[i][j] = dp[i-1][j-1] + 1;
当A[i] != B[j]时,dp[i][j] = max(dp[i-1][j], dp[i][j-1])。
其中max(a, b)表示a和b中的较大值。
最终,最长公共子序列的长度即为dp[m][n]的值。
接下来,我们来看一个具体的例题:给定两个字符串str1和str2,求它们的最长公共子序列。
我们可以按照上述递推式来设计动态规划算法。具体地,我们可以用一个二维数组dp来记录最长公共子序列的长度,其中dp[i][j]表示str1的前i个字符和str2的前j个字符的最长公共子序列的长度。
根据上述递推式,我们可以得到如下的动态规划代码:
```python
def longest_common_subsequence(str1, str2):
m, n = len(str1), len(str2)
dp = [[0] * (n+1) for _ in range(m+1)]
for i in range(1, m+1):
for j in range(1, n+1):
if str1[i-1] == str2[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[m][n]
```
如果我们需要找出最长公共子序列的具体内容,我们可以在动态规划的过程中记录一些额外的信息。例如,用一个二维数组path来记录dp[i][j]的值是从哪个状态转移而来的。具体来说,如果dp[i][j]是从dp[i-1][j-1]+1转移而来,则令path[i][j] = '↖';如果dp[i][j]是从dp[i-1][j]转移而来,则令path[i][j] = '↑';如果dp[i][j]是从dp[i][j-1]转移而来,则令path[i][j] = '←'。
最后,我们可以根据path数组来回溯出最长公共子序列的具体内容。
```python
def longest_common_subsequence(str1, str2):
m, n = len(str1), len(str2)
dp = [[0] * (n+1) for _ in range(m+1)]
path = [[''] * (n+1) for _ in range(m+1)]
for i in range(1, m+1):
for j in range(1, n+1):
if str1[i-1] == str2[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
path[i][j] = '↖'
elif dp[i-1][j] > dp[i][j-1]:
dp[i][j] = dp[i-1][j]
path[i][j] = '↑'
else:
dp[i][j] = dp[i][j-1]
path[i][j] = '←'
i, j = m, n
lcs = []
while i > 0 and j > 0:
if path[i][j] == '↖':
lcs.append(str1[i-1])
i -= 1
j -= 1
elif path[i][j] == '↑':
i -= 1
else:
j -= 1
lcs.reverse()
return ''.join(lcs)
```
上述代码中,lcs即为最长公共子序列。
阅读全文