FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

algorithm/DynamicProgramming/02_LongestCommonSubsequence at master · lixinchn/algorithm · GitHub

Repository navigation

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

README.md

layout post
title (Dynamic Programming) Longest Common Subsequence

描述

给定两个字符串,找出两个字符串包含的最长子串。

分析

此题是一道典型的动态规划,下面给出分析步骤。


假设两个字符串分别为 'abcdef', 'acbcf' 初始状态如下:

字符串 a b c d e f
0 0 0 0 0 0 0
a 0
c 0
b 0
c 0
f 0

第一步:如果第二个字符串只有一个字符,那么得到下表

字符串 a b c d e f
0 0 0 0 0 0 0
a 0 1 1 1 1 1 1
c 0
b 0
c 0
f 0
  依次向右比较的过程中,发现第二个字符串中的 'a' 于第一个字符串中的 'a' 相等,此时dp[1][1] = 1 + dp[0][0] = 1。
  
  之所以要加上dp[0][0],是因为发现相等字符以后,还要加上去掉当前字符后,之前出现的最大子串长度,此时因为第二个字符串只有 'a',所以当前只能取dp[0][0]。
  
  而当接着向后比较的过程中,并没有再次出现相等的情形,所以dp[1][1 + n] = 1,都取上一次出现的最大值。

第二步:使用第二个字符串中的下一个字符,那么得到下表

字符串 a b c d e f
0 0 0 0 0 0 0
a 0 1 1 1 1 1 1
c 0 1 1 2 2 2 2
b 0
c 0
f 0
  此时有两点需要说明。
  
  1. 当 'c' 与 'a' 进行比较时,发现不相等,此时要取左边或者上边数字较大者。其实也很好理解,取左边意味着取 'c' 之前得到的最大子串长度,取上边意味着取去掉 'c' 得到的最大子串长度。
  
  2. 当发现 'c' 相等时。dp[2][3] = 1 + dp[2 - 1][3 - 1]。也就是要加上两个字符串都去掉 'c' 之后得到的最长子串的长度。

以此类推,得到最终的表格

字符串 a b c d e f
0 0 0 0 0 0 0
a 0 1 1 1 1 1 1
c 0 1 1 2 2 2 2
b 0 1 2 2 2 2 2
c 0 1 2 3 3 3 3
f 0 1 2 3 3 3 4

可以得出转移方程:

        max(dp[i - 1][j], dp[i][j - 1] if 当前字符不相等

dp[i][j] =

        dp[i - 1][j - 1] + 1 if 当前字符相等

Python Code

class Solution():
    def do(self, str1, str2):
        len_str1, len_str2 = len(str1), len(str2)
        dp = [[0] * (len_str1 + 1) for _ in range(len_str2 + 1)]
        '''
        dp[i][j] = 
                    max(dp[i - 1][j], dp[i][j - 1]) if str1[j] != str2[i]
                    dp[i - 1][j - 1] + 1 if str1[j] == str2[i]
        '''
        for i in range(1, len_str2 + 1):
            for j in range(1, len_str1 + 1):
                if str1[j - 1] == str2[i - 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]

solution = Solution()
print solution.do('abcdef', 'acbcf')
print solution.do('abcdca', 'acbc')

Back | FazBrowse Home | New Git URL