-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
动态规划:最长公共子序列 LCS #131
Comments
貌似简明的递归def LCS(n1, n2, a, b):
if n1 < 0 or n2 < 0:
return 0
if a[n1] == b[n2]:
return 1 + LCS(n1 - 1, n2 - 1, a, b)
return max(LCS(n1 - 1, n2, a, b), LCS(n1, n2 - 1, a, b)) a = 'weare'
b = 'are'
LCS(len(a)-1, len(b)-1, a, b)
# 3 a = 'iwanttobeagreatman'
b = 'styleisthekeything'
LCS(len(a)-1, len(b)-1, a, b)
# 等待很久也没有出来结果 看来这个貌似简明的递归版重复计算太多太多。 |
带 memoizatation 的繁冗但有效降低复杂度的递归版本cache = {}
def LCS(n1, n2, a, b):
if (n1, n2) in cache:
return cache[(n1, n2)]
if n1 < 0 or n2 < 0:
res = 0
elif a[n1] == b[n2]:
res = 1 + LCS(n1 - 1, n2 - 1, a, b)
else:
res = max(LCS(n1 - 1, n2, a, b), LCS(n1, n2 - 1, a, b))
cache[(n1, n2)] = res
return res a = 'iwanttobeagreatman'
b = 'styleisthekeything'
LCS(len(a)-1, len(b)-1, a, b)
# 瞬间出结果: 6 来看一下 cache 的数据结构:
a b 的长度正好都是 18。 转制为 19 x 19 的表格,换个角度看一下: [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 0],
[0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 0],
[0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 0],
[0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4],
[0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4],
[0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4],
[0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4],
[0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 5],
[0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 5],
[0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 5],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6]] |
至拙至巧的迭代根据上述 cache 的数据结构可以断定动态规划的可行性:初始化一个二维数组,然后从左上角迭代到右下角即可得出答案。复杂度为 len(a) * len(b)。 def LCS(n1, n2, a, b):
T = [[0] * (len(a) + 1) for _ in range(len(b) + 1)]
for i in range(1, len(a) + 1):
for j in range(1, len(b) + 1):
if a[i -1] == b[j - 1]:
T[i][j] = T[i - 1][j - 1] + 1
else:
T[i][j] = max(T[i - 1][j], T[i][j - 1])
print(T)
return T[i][j]
看看迭代版产生的数据结构: [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2],
[0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3],
[0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3],
[0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3],
[0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3],
[0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3],
[0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4],
[0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4],
[0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4],
[0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4],
[0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 5],
[0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 5],
[0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 5],
[0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6]] |
递归和迭代产生的数据结构还是有不一样之处的。这也恰恰说明迭代版还有进一步提升性能的空间。不过那都已经是常数意义上的优化。 把动态规划这套解体思路再次运用一遍,力争由生到熟。 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
给定两个字符串 a, b, 求这两个字符串最长的公共子序列的长度。
a = 'weare', b = 'are' -> 很明显,是3。但如何给出一个通用的算法吗?
The text was updated successfully, but these errors were encountered: