最长公共子序列(LCS):最长公共子序列问题是在一组序列(通常2个)中找到最长公共子序列(注意:不同于子串,LCS不需要是连续的子串,
但是各个元素之间的相对顺序不能改变)
但是最长公共子序列和最长公共子串的问题都类似于爬楼梯问题,对于不要求各元素连续的LCS问题来说:当求两字符串[0,i]和[0,j]这两个区间
中的最长公共子序列dp[i][j]有2种来源:
(1)当字符串1的第i个元素和字符串2的第j个元素相同的时候:dp[i][j] = dp[i-1][j-1] + 1
(2) 如果不同的话,在[0,i]和[0,j]这两段区间中的最长公共子序列肯定不等于dp[i-1][j-1] + 1了,它应该由两种可能,可能等于dp[i-1][j] 或者 dp[i][j-1],又因为题目要最大值所以就对两个可能的来源取最大值。
最长公共子串问题:
和最长公共子序列的思路大体类似,区别在于最长公共子串问题的dp[i][j]只有一个可能来源,因为最长公共子序列需要是连续的,对dp[i][j]来说如果第i个元素和j元素不同的话,即使dp[i-1][j-1]不为0,dp[i][j] 也是为 0,因为需要连续,
如果第i个元素和j元素相同的话,dp[i][j] = dp[i-1][j-1] + 1
LintCode 上有最长公共子序列(不要求连续)的题目:
? https://www.lintcode.com/problem/longest-common-subsequence/description
class Solution:
"""
@param A: A string
@param B: A string
@return: The length of longest common subsequence of A and B
"""
def longestCommonSubsequence(self, A, B):
# write your code here
m = len(A)
n = len(B)
dp = [[0 for i in range(n + 1)] for j in range(m + 1)]
for i in range(m + 1):
for j in range(n + 1):
if i == 0 or j == 0:
dp[i][j] = 0
continue
if A[i - 1] == B[j - 1]:
dp[i][j] = dp[i-1][j-1] + 1
else:
dp[i][j] = max(dp[i][j-1],dp[i-1][j]) # A[i - 1] != B[j - 1] 所以dp[i][j] 取 max(dp[i][j-1],dp[i-1][j]) 不是 max(dp[i][j-1],dp[i-1][j]) + 1 因为最长公共子序列的长度没有增加
return dp[m][n]
LintCode 上的最长公共子串(要求连续)问题:
? https://www.lintcode.com/problem/longest-common-substring/description
class Solution:
"""
@param A: A string
@param B: A string
@return: the length of the longest common substring.
"""
def longestCommonSubstring(self, A, B):
# write your code here
m = len(A)
n = len(B)
if m == 0 or n == 0:
return 0
res = 0
dp = [[0 for i in range(n + 1)] for j in range(m + 1)]
for i in range(1,m + 1):
for j in range(1,n + 1):
# if i == 0 or j == 0:
# continue
if A[i - 1] == B[j - 1]:
dp[i][j] = dp[i-1][j-1] + 1
res = max(res,dp[i][j])
return res
# 暴力做法:
class Solution:
"""
@param A: A string
@param B: A string
@return: the length of the longest common substring.
"""
def longestCommonSubstring(self, A, B):
# write your code here
lena = len(A)
lenb = len(B)
res = 0
if lena < lenb:
C = B
B = A
A = C
lena = lenb
lenb = len(A)
for i in range(lena):
for j in range(i,lena):
if A[i:j+1] in B:
res = max(res,j - i + 1)
return res