找到字符串X的最长子序列,它是字符串Y的子字符串

时间:2014-10-09 17:59:07

标签: python string algorithm substring subsequence

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

这是我的暴力解决方案:

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

    这是一种更好的方法,可能通过DP吗?

    编辑:

    以下是我想解决的一个例子:

    Y: 'BACDBDCD'
    X: 'ABCD'
    

    答案是'ACD',因为'ACD'是X 的最长子序列,它也是Y 子串。

2 个答案:

答案 0 :(得分:1)

这有两种方法(两者都有多项式时间复杂度) 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)  

对于所有有效f0i的初始值为j。 答案是f(n, j)中所有有效j的最大值。

答案 1 :(得分:0)

在 Python 中,您不需要动态编程来解决它。利用运行时修改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)