a=hellowolrd
b=loop

# 思路

1. 先暴力破解：穷举
2. 更高效地穷举
3. 更高效地穷举+备忘录
4. 动态规划

## 1. dfs暴力收集所有解，再计算出最大解

import copy

def long_common_subsequence_all(str1, str2):
len1, len2 = len(str1), len(str2)
res_list = []
lcs = ""

def dp(i, j, track1, track2):
if i == len1 or j == len2:
nonlocal lcs
cs = "".join(track1)
res_list.append(cs)  # 到头了，收集一下公共子序列
if len(cs) >= len(lcs):
lcs = cs  # 更新最大子序列
return

c_track1 = copy.copy(track1)
c_track2 = copy.copy(track2)

if str1[i] == str2[j]:
# 找到一个lcs中的元素，str1和str2分别选中，继续往下找
c_track1.append(str1[i])
c_track2.append(str2[j])
dp(i + 1, j + 1, c_track1, c_track2)
return
else:
dp(i, j + 1, c_track1, c_track2)
dp(i + 1, j, c_track1, c_track2)

dp(0, 0, [], [])
return lcs, res_list

s1 = "chenqionghexsfz"
s2 = "cqhxsfz"
lcs, res_list = long_common_subsequence_all(s1, s2)
print(res_list)
print(lcs)

res_list是穷举所有的公共子串

## 2. dfs暴力只收集最大解

s1[0:i]和s2[0:j]的最长公共子串

# dp定义：返回text1[0:i]和text2[0:j]的lcs
def long_common_subsequence_all(text1, text2):
def dp(i, j):
if i == -1 or j == -1:
return 0
if text1[i] == text2[j]:
return dp(i - 1, j - 1) + 1
else:
return max(dp(i - 1, j), dp(i, j - 1))  # i和j不相同，分别再对比s1[i-1],s2[j]和s[i],s2[j-1]

return dp(len(text1) - 1, len(text2) - 1)

s1 = "chenqionghexsfz"
s2 = "cqhxsfz"
lcs_len = long_common_subsequence_all(s1, s2)
print(lcs_len)

def long_common_subsequence_all(str1, str2):
lcs = ""
# 定义dp：返回str1[0:i]和str2[0:j]的lcs
def dp(i, j, track1, track2):
nonlocal lcs
if i == -1 or j == -1:
# 到头了，更新最大的结果
cs = "".join(track1)
if len(cs) > len(lcs):
lcs = cs
return 0

c_track1 = copy.copy(track1)
c_track2 = copy.copy(track2)
if str1[i] == str2[j]:
# 找到一个lcs中的元素，str1和str2分别选中，继续往下找
c_track1.insert(0, str1[i])
c_track2.insert(0, str2[j])
return dp(i - 1, j - 1, c_track1, c_track2) + 1

else:
# i和j不相同，分别再对比s1[i-1],s2[j]和s[i],s2[j-1]
return max(dp(i - 1, j, c_track1, c_track2), dp(i, j - 1, c_track1, c_track2))

lcs_len = dp(len(str1) - 1, len(str2) - 1, [], [])
return lcs, lcs_len

s1 = "chenqionghexsfz"
s2 = "cqhxsfz"
lcs, lcs_len = long_common_subsequence_all(s1, s2)
print(lcs, lcs_len)

## 3. dfs暴力只收集最大解+备忘录

dp(3,5) = dp(2,4)+1
dp(2,5) = dp(2,4)+1

def long_common_subsequence(text1, text2):
memo = {}

def dp(i, j):
if (i, j) in memo:
return memo[(i, j)]
if i == -1 or j == -1:
return 0
if text1[i] == text2[j]:
return dp(i - 1, j - 1) + 1
else:
memo[(i, j)] = max(dp(i - 1, j), dp(i, j - 1))  # i和j不相同，分别再对比s1[i-1],s2[j]和s[i],s2[j-1]
return memo[(i, j)]

return dp(len(text1) - 1, len(text2) - 1)

s1 = "chenqionghexsfz"
s2 = "cqhxsfz"
lcs = long_common_subsequence(s1, s2)
print(lcs)

## 4. dp动态规划

dp(i,j)是返回text1,text2的最大公共子串大小。

dp[i][j]也是返回text1,text2的最大公共子串大小，只是反着来

# dp定义：返回text1[0:i]和text2[0:j]的lcs
def long_common_subsequence(text1, text2):
len1, len2 = len(text1), len(text2)
dp = [[0] * (len2 + 1) for _ in range(len1 + 1)]
for i in range(1, len1 + 1):
for j in range(1, len2 + 1):
# 找到一个公共字符串
if text1[i - 1] == text2[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[-1][-1]

s1 = "chenqionghexsfz"
s2 = "cqhxsfz"
lcs = long_common_subsequence(s1, s2)
print(lcs)

posted @ 2021-09-27 17:34  雪山飞猪  阅读(223)  评论(0编辑  收藏  举报