0

I have a recursive solution to the longest common subsequence problem of two strings given below:

def LCS(i, j, lcs): # i , j are the position of character in X and Y respectively which are being compared
                    # lcs is the string storing the current longest common subsequence
    print(i, j, lcs)
    if i == 0 or j == 0: # basic case
        return lcs

    if X[i - 1] == Y[j - 1]:  # increment lcs 
        lcs = X[i - 1] + lcs
        return lcs

  # else check for LCS(i-1,j) and LCS(i,j-1)

    lcs_copy = str(lcs)
    lcs1 = LCS(i - 1, j, lcs_copy)
    x = len(lcs1)
    lcs_copy = str(lcs)
    lcs2 = LCS(i, j - 1, lcs_copy)
    y = len(lcs2)

    if x > y:
        lcs = lcs1
    else:
        lcs = lcs2
    return lcs


X = 'abcbddab'
Y = 'bdcaba'
lcs = ''
lcs = LCS(8, 6, lcs)
print(lcs)

but it doesn't give the desired result. any suggestion where might be the issue?

Mr Sukhe
  • 67
  • 9
  • Seems with a correction to the base case this would provide the longest common subsequence not longest common substring i.e. [modification of](https://www.geeksforgeeks.org/python-program-for-longest-common-subsequence/) – DarrylG Jun 14 '20 at 11:58
  • @DarrylG , my bad, I should have mentioned longest common subsequence in the problem. Actually this is not giving the longest common subsequence. – Mr Sukhe Jun 14 '20 at 12:41

1 Answers1

0

Keeping most of OP code we have two corrections:

  1. The base case needs recursive call
  2. No need to copy string lcs before calling recursively

Code

def LCS(i, j, lcs):
  """i , j are the position of character in X and Y respectively which are being compared
      lcs is the string storing the current longest common substring"""

  # Base Cases
  if i == 0 or j == 0: # basic case
      return lcs

  if X[i - 1] == Y[j - 1]: 
      # add current string to longest of
      # precusor strings
      return LCS(i-1, j-1, X[i - 1] + lcs)

  # else: check for LCS(i-1,j) and LCS(i,j-1)
  lcs1 = LCS(i - 1, j, lcs)
  lcs2 = LCS(i, j - 1, lcs)

  if len(lcs1) > len(lcs2):
      return lcs1
  else:
      return lcs2

Test

X = 'abcbddab'
Y = 'bdcaba'
lcs = ''
lcs = LCS(8, 6, lcs)
print(lcs)  # Output: bdab

Rewriting function

  1. The function should be self-contained (no need to refer to global X, Y)
  2. Use PEP 8 function naming convention

Refactored Code

def lcs(str1, str2):
  """input strings str1, str2"""

  # Base Case
  if not str1 or not str2: # one is empty
      return ""

  if str1[-1] == str2[-1]: 
      # add current string to longest of
      # precusor strings
      return lcs(str1[:-1], str2[:-1]) + str1[-1]

  # else check for LCS(i-1,j) and LCS(i,j-1)
  return max(lcs(str1[:-1], str2), lcs(str1, str2[:-1]), key = len)

print(lcs('abcbddab', 'bdcaba'))
# Output: bcba (different longest sequence but same length)
DarrylG
  • 16,732
  • 2
  • 17
  • 23