子串与子序列的区别
最长公共子串(The Longest Common Substring)和最长公共子序列(The Longest Common Subsequence)的区别在于,前者需要连续,而后者不要求连续。例如:a = "12345.6789",b = “234.189”,那么a与b的最长公共子串为"234",最长公共子序列为"234.89"。
最长公共子串(简单一点,可爱多了)
思路:构建一个二维数组,记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则在上一个字符匹配情况基础上加1,同时记录最长匹配长度,以及字符串匹配的开始下标。
def LongestCommonSubstr(s1, s2):
len_s1 = len(s1)
len_s2 = len(s2)
# 为了方便后面记录,多加一行一列
record = [[0 for j in range(len_s2 + 1)] for i in range(len_s1 + 1)]
maxNum = 0 # 最长匹配长度
p = 0 # 字符串匹配的开始下标
for i in range(len_s1):
for j in range(len_s2):
if s1[i] == s2[j]:
# 相同则累加
record[i + 1][j + 1] = record[i][j] + 1
if record[i + 1][j + 1] > maxNum:
maxNum = record[i + 1][j + 1]
p = i
return maxNum, s1[p + 1 - maxNum:p + 1]
最长公共子序列(糟老头)
(最长公共子序列是一个十分实用的问题,可以描述两段文字之间的相似度,你想想你的论文查重是怎么来的?)
思想:(参考博客:https://blog.csdn.net/littlethunder/article/details/25637173)
1、找出最优解特性,并刻画其结构特性(不着急,看完有糖)
假设有长度为m的序列a、长度为n的序列b,如果 a[m-1] == b[n-1],那么 a[:m] 和 b[:n]的最长公共子序列长度就是 a[:m-1] 和 b[:n-1]的最长公共子序列长度加1;如果 a[m-1] != b[n-1],那么 a[:m] 和 b[:n]的最长公共子序列长度就是 max(x,y) 其中,x 代表 a[:m-1] 和 b[:n] 的最长公共子序列长度,y 代表 a[:m] 和 b[:n-1] 的最长公共子序列长度。
2、递归定义最优解
3、写代码
def LongestCommonSubseq(a, b):
len_a = len(a)
len_b = len(b)
# 记录长度
c = [[0 for j in range(len_b + 1)] for i in range(len_a + 1)]
# 记录公共子序列
res = []
for i in range(len_a):
for j in range(len_b):
if a[i] == b[j]:
c[i + 1][j + 1] = c[i][j] + 1
res.append(a[i])
else:
# c[i][j+1] 位于 c[i+1][j+1] 的上边
# c[i+1][j] 位于 c[i+1][j+1] 的左边
c[i + 1][j + 1] = max(c[i][j + 1], c[i + 1][j])
res = ''.join(res)
maxNum = c[-1][-1] # 最长公共子序列的长度
return maxNum, res
print(LongestCommonSubseq("12345678", '13579'))