【python】求最长连续公共子序列长度的几种解法

这篇具有很好参考价值的文章主要介绍了【python】求最长连续公共子序列长度的几种解法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目:

 

给定两个序列X和Y,返回最长连续的公共子序列长度。如果没有连续公共子序列,返回0.

X和Y的元素都是整数。

示例:

输入:

1 5 7 3 4 5
7 3 4 4 5 7 -2

输出:

3

 说明:

最长的连续公共子序列是[7,3,4] (X[2:4] 和Y[0:2])

这道题在【leetcode1143】的基础上增加了公共子序列连续的限制。解法可以有以下几种:

题解:

1. 动态规划

创建m+1 行 n+1 列的二维数组dp,其中 dp[i][j] 表示 a和b分别以a[i-1],b[j-1]结尾的最长公共子序列的长度。

可以得到状态转移方程如下:

python 最长连续子序列,刷题日记,动态规划,python,hash,算法

最终计算dp中的最大值即为最长公共连续子序列的长度。

def findLength(a,b):
    m,n=len(a),len(b)
    maxlength=0
    dp=[[0]*(n+1) for i in range(m+1)]
    for i in range(m+1):
        for j in range(n+1):
            if a[i-1]==b[j-1]:
                dp[i][j]=dp[i-1][j-1]+1
                maxlength=max(maxlength,dp[i][j])
    return maxlength

时间复杂度:O(mn)

空间复杂度:O(mn),可以优化至O(m)或O(n)(只存储dp矩阵的两列进行计算)

2. 后缀数组

def longestCommonSubstring(A, B):
    if A == None or B == None:
        return
    C = [9999]
    s = A + C + B
    indexOfSharp = len(A)
    SA = suffixArray(s)
    maxLen, maxIndex = 0, 0
    hasCommon = False
    for i in range(len(s) - 1):
        # 判断后缀数组中两个相邻元素对应的后缀字符串是否位于“#”两侧,即是否属于A和B两个不同字符串
        diff = (SA[i] - indexOfSharp) * (SA[i + 1] - indexOfSharp)
        if diff < 0:
            tempLen = comlen(s, SA[i], SA[i + 1])
            if tempLen > maxLen:
                maxLen = tempLen
                maxIndex = SA[i]
                hasCommon = True
    return (maxLen, s[maxIndex:maxIndex + maxLen]) if hasCommon else False
# 得到一个字符串的后缀数组
def suffixArray(s):
    if s == None or len(s) == 0:
        return None
    allSuffix = []
    for i in range(len(s)):
        allSuffix.append([s[i:], i])
    sortedList = sorted(allSuffix)
    SA = [w[1] for w in sortedList]
    return SA
# 比较得到后缀数组中两个相邻的元素分别对应的后缀字符串的最长前缀
def comlen(s, p, q):
    j = 0
    while j < len(s[p:]) and j < len(s[q:]) and s[p:p + j + 1] == s[q:q + j + 1]:
        j += 1
    return j

时间复杂度:O(nlgn)

空间复杂度:O(n^2)

3. 哈希表+二分查找

设最长公共子串的长度为x,那么x在0到min(len(X),len(Y))之间,并且满足二分的性质。因为如果存在长度为m的公共子序列,那么必然存在长度小于m的公共子序列。先哈希一下这两个序列,二分长度。每次check的时候,假设判断是否存在长度为k的公共子串,那么看字符串1和字符串2长度为k的子串的哈希值有没有相同的,如果有返回true,没有返回false;然后使用二分查找最长公共子串长度x.

def findLen(X, Y):
    base, mod = 113, 10**9 + 9

    def checkHash(l):

        # Construct hash value set of X[0:l]
        hx = 0
        for i in range(l):
            hx = (hx * base + X[i]) % mod
        hvx = {hx}
        pow_base = pow(base, l - 1, mod)
        for i in range(l, len(X)):
            hx = ((hx - X[i - l] * pow_base) * base + X[i]) % mod
            hvx.add(hx)
        
        # Construct hash value set of Y[0:l] and check whether there is an hash value that matches 
        hy = 0
        for i in range(l):
            hy = (hy * base + Y[i]) % mod
        if hy in hvx:
            return True
        for i in range(l, len(Y)):
            hy = ((hy - Y[i - l] * pow_base) * base + Y[i]) % mod
            if hy in hvx:
                return True

        return False

    # Binary Search
    l, r = 0, min(len(X), len(Y))
    res = 0
    while l <= r:
        m = (l + r) // 2
        if checkHash(m):
            res = m
            l = m + 1
        else:
            r = m - 1
    return res

时间复杂度:O(nlogn)

空间复杂度:O(n)

4.双指针文章来源地址https://www.toymoban.com/news/detail-690525.html

def findLength(a, b):
    aa = ''.join(a)
    l, s = 1, 0
    l1, l2 = len(a), len(b)
    rtn = 0
    while l <= l1 and l+s <= l2:
        e = s + l
        temp = ''.join(b[s:e])
        if temp in aa:
            rtn = max(rtn, l)
            l += 1
        else:
           if str(b[e-1]) not in aa:
                s = e
           else:
                s += 1
                
           if s + rtn >= l2:
                return rtn
    return rtn

到了这里,关于【python】求最长连续公共子序列长度的几种解法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 接一元二次方程的几种解法,用python代码实现

    一元二次方程的解法有以下几种:公式法、因式分解法、配方法、求根公式法。 下面是使用Python代码实现一元二次方程的解法: ```python import math def solve_quadratic_equation(a, b, c):     delta = b**2 - 4*a*c     if delta 0:         return \\\"无实根\\\"     elif delta == 0:         x = -b / (2*a)    

    2024年02月07日
    浏览(46)
  • 最长公共子序列和最长公共子串

    最长公共子序列 题目描述 给出1,2,…, n 的两个排列P 1 和 P 2 ,求它们的最长公共子序列。 输入格式 第一行是一个数 n 。 接下来两行,每行为 n 个数,为自然数1,2,…, n 的一个排列。 输出格式 一个数,即最长公共子序列的长度。 题目分析 第一阶段定义dp数组 (1)考虑规模

    2024年02月19日
    浏览(38)
  • 最长公共子序列(详细代码 注释 分析 以及求出最长公共子序列内容方法)

    文章有些长,希望能够耐心看完,并且对你有帮助,文章是自己看了书之后,总结的,如果有什么错误的地方,欢迎指出。 一些基本的概念: 子序列: 原序列中删除若干个元素得到的序列,即原序列中可以不连续的一段 子串: 原序列中任意个连续的序列元素组成的序列,

    2023年04月15日
    浏览(50)
  • Day.1 LeetCode刷题练习(最长公共前缀 C/C++两种解法)

    题目: 例子: 分析题目: 主要目的:求出各个字符串的公共前缀 思路(本人解法): 用所给实例来看,不难看出我们可以直接以竖着对应来查看是否是公共前缀 ,  这样就有了一定的思路 , 然后接着想如何让他找到最长的公共前缀后就 停止下来呢  这样就能想到,从最

    2024年02月11日
    浏览(38)
  • 【算法训练-字符串 三】最长公共子串、最长公共子序列

    废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【】,使用【】这个基本的数据结构来实现,这个高频题的站点是: CodeTop ,筛选条件为: 目标公司+最近一年+出现频率排序 ,由高到低的去 牛客TOP101 去找,只有两个地方都出现过才做

    2024年02月09日
    浏览(39)
  • day55 最长递增子序列 最长连续递增子序列 最长重复子数组

    题目链接 300 最长递增子序列 题意 找到整数数组nums的最长严格递增子序列的长度(子序列并不改变原始的顺序,但是可以删除元素) 动态规划 动规五部曲 1)dp数组及下标i的含义 dp[i] 表示以nums[i]为结尾的最长递增子序列的长度 2)dp数组初始化 根据定义 长度至少是1  dp

    2024年04月11日
    浏览(61)
  • Leetcode:300. 最长递增子序列、674. 最长连续递增序列(C++)

    目录 300. 最长递增子序列 题目描述: 实现代码: 原理思路: 674. 最长连续递增序列 题目描述: 实现代码: 原理思路: 题目描述:         给你一个整数数组  nums  ,找到其中最长严格递增子序列的长度。 子序列  是由数组派生而来的序列,删除(或不删除)数组中

    2024年02月11日
    浏览(57)
  • 最长公共子序列

    最长公共子序列,英文缩写为LCS (Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。 子串、子序列还有公共子序列的概念(在上篇LIS中也曾涉及过) ,我们以字

    2024年02月16日
    浏览(36)
  • 动态规划--最长公共子序列

    动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题﹐ 即将大规模变成小规模 ,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是﹐适合于用动态规划法求解的问题,经分解得到的子问题往往不是互相独立的。 他们之间有关系

    2024年02月04日
    浏览(76)
  • 最长公共子序列LCA

    题目链接:3692. 最长连续公共子序列 - AcWing题库

    2024年02月13日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包