【算法 in python | DP】LCS最长公共子串

1. LCS,最长公共子串

动态规划,状态转移方程:

Longest Common Subsequence Problem

#该版本是返回最长公共子串和其长度,若只返回长度,则可以简化
def lcs(s1, s2):
    l1 = len(s1)
    l2 = len(s2)
    # res[i][j]存储子串s1[0:i] 和 子串s2[0:j] 的lcs串
    # num[i][j]存储子串s1[0:i] 和 子串s2[0:j] 的lcs长度
    #由于考虑到空串也作为比较元素,则将两个字符串的长度各加一
    res = [['' for i in range(l2+1)] for j in range(l1+1)]
    num = [[0 for i in range(l2+1)] for j in range(l1+1)]
    for i in range(1,l1+1):
        for j in range(1, l2+1):
            if s1[i-1] == s2[j-1]:
                num[i][j] = num[i-1][j-1]+1
                res[i][j] = res[i-1][j-1] + s1[i-1]
            else:
                if num[i-1][j] > num[i][j-1]:
                    num[i][j] = num[i-1][j]
                    res[i][j] = res[i-1][j]
                else:
                    num[i][j] = num[i][j-1]
                    res[i][j] = res[i][j-1]
    return num[-1][-1],res[-1][-1]

简化版本:只返回最长LCS的长度。

def lcs(s1, s2):
    l1 = len(s1)
    l2 = len(s2)
    # num[i][j]存储子串s1[0:i] 和 子串s2[0:j] 的lcs长度
    #由于考虑到空串也作为比较元素,则将两个字符串的长度各加一
    num = [[0 for i in range(l2+1)] for j in range(l1+1)]
    for i in range(1,l1+1):
        for j in range(1, l2+1):
            if s1[i-1] == s2[j-1]:
                num[i][j] = num[i-1][j-1]+1
            else:
                num[i][j] = max(num[i-1][j], num[i][j-1])
    return num[-1][-1]

2. 平方串

如果一个字符串S是由两个字符串T连接而成,即S = T + T, 我们就称S叫做平方串,例如"","aabaab","xxxx"都是平方串.
牛牛现在有一个字符串s,请你帮助牛牛从s中移除尽量少的字符,让剩下的字符串是一个平方串。换句话说,就是找出s的最长子序列并且这个子序列构成一个平方串。 

即将s分成两个子串,找出两个子串的lcs,然后取最大的lcs的二倍。

def squreStr(s):
    #将s分成两个子串,找出对应的lcs,在所有的lcs中找出最大的,其二倍即为对应的平方串的长度
    res = 0
    for i in range(1,len(s)):
        s1 = s[0:i]
        s2 = s[i:]
        res = max(res,lcs(s1,s2))
    return res*2

猜你喜欢

转载自blog.csdn.net/u013166817/article/details/83578665