《面试》-- 大白话谈最长公共子串、最长公共子序列的问题(Python)

子串与子序列的区别

最长公共子串(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'))

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值