Python 查找字符串X的最长子序列,该子序列是字符串Y的子字符串

Python 查找字符串X的最长子序列,该子序列是字符串Y的子字符串,python,string,algorithm,substring,subsequence,Python,String,Algorithm,Substring,Subsequence,我知道如何使用动态规划来解决给定两个字符串的最长公共子序列或最长公共子字符串的查找问题。但是,我很难找到一个解决方案来解决查找字符串X的最长子序列的问题,该子序列是字符串Y的子字符串 以下是我的暴力解决方案: 找到字符串X的所有子序列,并按长度desc对其排序 遍历已排序的子序列,如果当前子序列是Y的子字符串,则返回子序列 它可以工作,但运行时间可能不好。假设X中的所有字符都是唯一的,那么就有2^m个子串,其中m是X的长度。我认为检查一个字符串是否是Y的子串需要O(n),其中n是Y的长度。所以总

我知道如何使用动态规划来解决给定两个字符串的最长公共子序列或最长公共子字符串的查找问题。但是,我很难找到一个解决方案来解决查找字符串X的最长子序列的问题,该子序列是字符串Y的子字符串

以下是我的暴力解决方案:

  • 找到字符串X的所有子序列,并按长度desc对其排序
  • 遍历已排序的子序列,如果当前子序列是Y的子字符串,则返回子序列
  • 它可以工作,但运行时间可能不好。假设X中的所有字符都是唯一的,那么就有2^m个子串,其中m是X的长度。我认为检查一个字符串是否是Y的子串需要O(n),其中n是Y的长度。所以总的运行时间是O(n*2^m)

    是否有更好的方法,可能是通过DP

    编辑:

    下面是我想解决的一个示例:

    Y: 'BACDBDCD'
    X: 'ABCD'
    
    答案是“ACD”,因为“ACD”是X的最长子序列,也是Y的子序列。这里有两种方法(它们都有多项式时间复杂度)。
    1.生成Y的所有子串(有
    O(m^2)
    这样的子串)。对于每个子字符串,检查它是否是X的子序列(可以使用贪婪算法在线性时间内完成)。该算法具有
    O(n*m^2)
    时间复杂度,这已经不是那么糟糕了。
    2.如果速度不够快,可以使用动态规划实现时间复杂度
    O(n*m)
    。让我们定义
    f(i,j)
    =以X中的
    i-th
    位置和Y中的
    j-th
    位置结尾的最长答案。转换如下:

    f(i + 1, j) = max(f(i + 1, j), f(i, j)) //skip this character in X
    if X[i] == Y[j] //add this character to current answer
        f(i + 1, j + 1) = max(f(i + 1, j + 1), f(i, j) + 1)  
    
    对于所有有效的
    i
    j
    f
    的初始值为
    0

    答案是
    f(n,j)
    中的最大值,对于Python中所有有效的
    j

    ,您不需要动态编程来解决它。使用在运行时修改for循环语法的灵活性来实现它:

    current_len=0
    subseq_len = 0
    subseq_data=''
    array1 = "ABCBDAB"
    array2 = "BDCABA"
    #array1="MICHAELANGELO"
    #array2="HELLO"
    m=len(array1)
    n=len(array2)
    #loop over first string array1 
    #and increment index k to form new substrings of len-1
    for k in range(0,m):
        start=0
        current_len = 0
        cur_seq =''
        #substring starting at k to m of array1
        for i in range(k,m):
            for j in range(start,n):
                if array1[i]==array2[j]:
                    #increment length of matched subsequence
                    current_len +=1
                    #move forward index to point to remaining sub string array2
                    start=j+1
                    cur_seq = cur_seq+array1[i]
                    break
            #print(k)
            #print(":"+cur_seq)
        #Check if current iteration for k produced longer match
        if subseq_len < current_len:
            subseq_len = current_len
            subseq_data = cur_seq
        enter code here
    
    print(subseq_data)
    print(subseq_len)
    
    current\u len=0
    水下q_len=0
    subseq_数据=“”
    array1=“ABCBDAB”
    array2=“BDCABA”
    #array1=“MICHAELANGELO”
    #array2=“你好”
    m=len(阵列1)
    n=len(阵列2)
    #在第一个字符串数组1上循环
    #并增加索引k以形成len-1的新子串
    对于范围(0,m)内的k:
    开始=0
    当前长度=0
    当前顺序=“”
    #从阵列1的k到m开始的子串
    对于范围内的i(k,m):
    对于范围内的j(开始,n):
    如果阵列1[i]==阵列2[j]:
    #匹配子序列的增量长度
    当前长度+=1
    #向前移动索引以指向剩余的子字符串数组2
    开始=j+1
    当前顺序=当前顺序+阵列1[i]
    打破
    #印刷品(k)
    #打印(“:”+当前顺序)
    #检查k的当前迭代是否产生更长的匹配
    如果水下长度<当前长度:
    subseq_len=当前_len
    水下数据=当前顺序
    在这里输入代码
    打印(水下数据)
    打印(子标题)
    
    当您知道DP agorithm具有最佳的渐近复杂性时,为什么不使用它?为什么会有反对票?他说他想用DP。你看过。。。这非常清楚地表明,动态规划是正确的解决方案,以解决在多项式时间。。。你的第一句话说你已经知道怎么做了。。。那么问题是什么(我没有投反对票)[编辑也许我误读了你的开场白…你说你知道如何找到最常见的而不是最长的]@sscnapoli1926 DP是我正在寻找的解决方案,但我不知道怎么做。也许我的措辞令人困惑…@JoranBeasley我读过这篇文章,但我认为我的问题不同。请看我的编辑。第一个正是我所做的。对于第二个,我没有得到你的代码,你如何精确地计算f(I+1,j)?@Chuntaulu第一个不是你做的:你找到了X的所有子序列(可以是指数数),但我找到了Y的所有子序列(总是有多项式数的子序列)。第二个:我只是以递增的顺序迭代所有可能的I和j,并对f应用两个公式。对不起,你是对的,你的第一个解是不同的,我可以看到改进。对于第二个,f(i+1,j)出现在作业的两侧,这是如何工作的呢???@Chuntaulu最初,
    f
    0
    对于所有
    i
    j
    。然后根据公式进行更新(如果新值更大)。如果f(i+1,j),那么它可以重写为
    ,所以这里没有问题。