最长公共子串/子序列

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最长公共子串/子序列相关的知识,希望对你有一定的参考价值。

最长公共子串

问题描述:给定两个字符串,找到他们公共的子串,要求连续

   b  a  b

c  0  0  0

a  0  1  0

b  1  0  1

a  0  1  0

矩阵的斜对角线最长的那个就是最长公共子串。

不过在二维矩阵上找最长的由1组成的斜对角线也是件麻烦费时的事,下面改进:当要在矩阵是填1时让它等于其左上角元素加1。

   b  a  b

c  0  0  0

a  0  1  0

b  1  0  2

a  0  2  0

这样矩阵中的最大元素就是 最长公共子串的长度。

在构造这个二维矩阵的过程中由于得出矩阵的某一行后其上一行就没用了,所以实际上在程序中可以用一维数组来代替这个矩阵。

# 最长公共子串
# 解题思路:建立一个二阶矩阵,只需看对角线连续为1 的最长长度,
# 简化之,可以建立一个一维数组,不断更新,值若为1就加上左上角的值
from copy import deepcopy
class Solution:
    """
    @param: A: A string
    @param: B: A string
    @return: the length of the longest common substring.
    """
    def longestCommonSubstring(self, A, B):
        labelOfLastList = [0 for _ in range(len(A))]
        labelOfThisList = [0 for _ in range(len(A))]
        maxLength = 0
        for b in B:
            for i, a in enumerate(A):
                if a == b:
                    labelOfThisList[i] = 1 if i == 0 else labelOfLastList[i - 1] + 1
                else:
                    labelOfThisList[i] = 0
            labelOfLastList = deepcopy(labelOfThisList)
            maxOfThisList = max(labelOfThisList)
            if maxLength < maxOfThisList:
                maxLength = maxOfThisList
        return maxLength

A = ‘‘
B = ‘‘
X = Solution()
print(X.longestCommonSubstring(A, B))

最长公共子序列

问题描述:给定两个字符串,找到公共的子序列, 不要求连续

解决方法:利用动态规划,先找到最长公共子序列长度,

技术分享

回溯的方法:

采用一个标记函数Flag[i,j],当

①:C[i,j]=C[i-1,j-1]+1  时 标记Flag[i,j]="left_up";    (左上方箭头)

②:C[i-1,j]>=C[i,j-1]   时 标记Flag[i,j]="left";          (左箭头)

③: C[i-1,j]<C[i,j-1]     时 标记Flag[i,j]="up";            (上箭头)

注:这种方法只能找到一个子序列,实际上子序列有多种存在

# 最长公共子序列
# 和子串的区别在于,子序列不要求连续,也就是说一个长度为N的字符串,可以有2的N次方个子序列
# 解题思路:利用动态规划。
# C[i,j]表示两个字符串的前i个和前j个字符的最长公共子序列长度
# 然后回溯,找到最长公共子序列
def longestCommonSubsequence(A, B):
    lenA = len(A)
    lenB = len(B)
    longestLengthList = [[0 for _ in range(lenA + 1)] for _ in range(lenB + 1)]
    flag = [[0 for _ in range(lenA + 1)] for _ in range(lenB + 1)]
    for i in range(lenA + 1):  
        for j in range(lenB + 1):
            if i == 0 or j == 0:
                longestLengthList[i][j] = 0
            elif A[i - 1] == B[j - 1]:
                longestLengthList[i][j] = longestLengthList[i - 1][j - 1] + 1
                flag[i][j] = ‘leftUp‘
            elif longestLengthList[i][j - 1] >= longestLengthList[i - 1][j]:
                longestLengthList[i][j] = longestLengthList[i][j - 1]
                flag[i][j] = ‘left‘
            else:
                longestLengthList[i][j] = longestLengthList[i - 1][j]
                flag[i][j] = ‘up‘
    longestSubsequence = ‘‘
    longestLength = max(max(longestLengthList))
    i = lenA
    j = lenB
    while len(longestSubsequence) < longestLength:
        if flag[i][j] == ‘leftUp‘:
            longestSubsequence += A[i-1]
            i -= 1
            j -= 1
        elif flag[i][j] == ‘left‘:
            j -= 1
        elif flag[i][j] == ‘up‘:
            i -= 1

    return longestSubsequence[::-1]

A = ‘acgbfhk‘
B = ‘cegefkh‘
print(longestCommonSubsequence(A, B))

 

  参考博客:

http://www.cnblogs.com/zhangchaoyang/articles/2012070.html

http://www.cnblogs.com/huangxincheng/archive/2012/11/11/2764625.html

 

以上是关于最长公共子串/子序列的主要内容,如果未能解决你的问题,请参考以下文章

最长公共子串和最长公共子序列

最长公共子串与最长公共子序列

算法图解:动态规划之最长公共子串,最长公共子序列

每日一题-——最长公共子序列(LCS)与最长公共子串

最长公共子串

C语言实现最长公共子串与最长公共子序列