【问题标题】:Recursive solution to common longest substring between two strings两个字符串之间公共最长子串的递归解决方案
【发布时间】:2018-12-04 15:20:03
【问题描述】:

我试图返回两个字符串之间的公共子字符串的长度。我非常了解 DP 解决方案,但是我希望能够递归地解决这个问题,只是为了练习。

我有办法找到最长的公共子序列...

def get_substring(str1, str2, i, j):
    if i == 0 or j == 0:
        return
    elif str1[i-1] == str2[j-1]:
        return 1 + get_substring(str1, str2, i-1, j-1)
    else:
        return max(get_substring(str1, str2, i, j-1), get_substring(str1, str2, j-1, i))

但是,我需要最长的公共子字符串,而不是最长的公共字母序列。我尝试以多种方式更改我的代码,其中一种是将基本情况更改为...

if i == 0 or j == 0 or str1[i-1] != str2[j-1]:
    return 0

但这没有用,我的任何其他尝试也没有。

例如,对于以下字符串...

X = "AGGTAB"
Y = "BAGGTXAYB"
print(get_substring(X, Y, len(X), len(Y)))

最长的子串是AGGT

我的递归技能不是最好的,所以如果有人可以帮助我,那将非常有帮助。

【问题讨论】:

    标签: algorithm recursion


    【解决方案1】:

    您需要分别对每个进行递归。如果你有多个递归函数,这更容易做到。

    def longest_common_substr_at_both_start (str1, str2):
        if 0 == len(str1) or 0 == len(str2) or str1[0] != str2[0]:
            return ''
        else:
            return str1[0] + longest_common_substr_at_both_start(str1[1:], str2[1:])
    
    def longest_common_substr_at_first_start (str1, str2):
        if 0 == len(str2):
            return ''
        else:
            answer1 = longest_common_substr_at_both_start (str1, str2)
            answer2 = longest_common_substr_at_first_start (str1, str2[1:])
            return answer2 if len(answer1) < len(answer2) else answer1
    
    def longest_common_substr (str1, str2):
        if 0 == len(str1):
            return ''
        else:
            answer1 = longest_common_substr_at_first_start (str1, str2)
            answer2 = longest_common_substr(str1[1:], str2)
            return answer2 if len(answer1) < len(answer2) else answer1
    
    print(longest_common_substr("BAGGTXAYB","AGGTAB") )
    

    【讨论】:

    【解决方案2】:

    我很抱歉。我没有时间将其转换为递归函数。这是相对简单的作曲。如果 Python 有一个 fold 函数,那么递归函数将大大简化。 90% 的递归函数是原始的。这就是fold 如此有价值的原因。

    我希望其中的逻辑对递归版本有所帮助。

    (x,y)= "AGGTAB","BAGGTXAYB"
    xrng=  range(len(x)) # it is used twice
    
    np=[(a+1,a+2) for a in xrng] # make pairs of list index values to use
    
    allx = [ x[i:i+b] for (a,b) in np for i in xrng[:-a]] # make list of len>1 combinations
    
    [ c for i in range(len(y)) for c in allx if c == y[i:i+len(c)]] # run, matching x & y
    

    ...生成这个列表,从中获取最长的匹配项

    ['AG', 'AGG', 'AGGT', 'GG', 'GGT', 'GT']

    我没有意识到从列表中获得最长的匹配会有点麻烦。

    ls= ['AG', 'AGG', 'AGGT', 'GG', 'GGT', 'GT']
    ml= max([len(x) for x in ls])
    ls[[a for (a,b) in zip(range(len(ls)),[len(x) for x in ls]) if b == ml][0]]
    

    “AGGT”

    【讨论】:

      【解决方案3】:

      包 algo.dynamic;

      公共类 LongestCommonSubstring {

      public static void main(String[] args) {
          String a = "AGGTAB";
          String b = "BAGGTXAYB";
          int maxLcs = lcs(a.toCharArray(), b.toCharArray(), a.length(), b.length(), 0);
          System.out.println(maxLcs);
      }
      
      private static int lcs(char[] a, char[] b, int i, int j, int count) {
          if (i == 0 || j == 0)
              return count;
          if (a[i - 1] == b[j - 1]) {
              count = lcs(a, b, i - 1, j - 1, count + 1);
          }
          count = Math.max(count, Math.max(lcs(a, b, i, j - 1, 0), lcs(a, b, i - 1, j, 0)));
          return count;
      }
      

      }

      【讨论】:

        猜你喜欢
        • 2014-08-24
        • 1970-01-01
        • 2018-06-23
        • 1970-01-01
        • 2013-09-13
        • 1970-01-01
        相关资源
        最近更新 更多