基础题型:
- 最长共公共子序列(不连续)lcs
- 最长公共子串(连续)lcstr
- 最长回文子序列(不连续)lps
- 最长回文子串(连续)lpstr
拓展题型
- 平方串(lcs拓展)
- 给定一个字符串,问是否能通过添加一个字母将其变为回文串(lcstr拓展)
1. 最长公共子序列LCS
输入:‘abcdef’,‘agbcje’
输出:‘abce’
#该版本是返回最长公共子串和其长度,若只返回长度,则可以简化
def LCS(s1,s2):
m = len(s1)
n = len(s2)
res = [['' for i in range(n+1)] for j in range(m+1)]
for i in range(1,m+1):
for j in range(1,n+1):
if s1[i-1] == s2[j-1]:
res[i][j] = res[i-1][j-1] + s1[i-1]
else:
if len(res[i-1][j]) > len(res[i][j-1]):
res[i][j] = res[i-1][j]
else:
res[i][j] = res[i][j-1]
return 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. 最长公共子串
输入:‘abcdef’,‘agbcje’
输出:‘bc’
def findLongest(A, n, B, m):
val = 0
res = [[0 for i in range(m + 1)] for j in range(n + 1)]
for i in range(1, n + 1):
for j in range(1, m + 1):
if A[i - 1] == B[j - 1]:
res[i][j] = res[i - 1][j - 1] + 1
else:
res[i][j] = 0
val = max(val, res[i][j])
return val
3. 最长回文子序列
输入:‘aucbcia’
输出:5
状态初始条件:dp[i][i]=1 (i=0:n-1)
状态转移方程:dp[l][r]=dp[l+1][r-1] + 2 if(str[l]==str[r])
dp[l][r]=max(dp[l+1][r],dp[l][r-1]) if (str[l]!=str[r])
def LPS(s):
n = len(s)
res = [[0 for i in range(n)] for j in range(n)]
for i in range(n):
res[i][i] = 1
for r in range(n):
for l in range(r-1, -1,-1):
if s[l] == s[r]:
res[l][r] = res[l+1][r-1] + 2
else:
res[l][r] = max(res[l+1][r], res[l][r-1])
return res[0][n-1]
4. 最长回文子串
输入:‘aucbcia’
输出:5
初始条件:dp[i][i]=1,dp[i][i+1] = (S[i] == S[i+1]) ? 1 : 0。
def LPSeq(s):
n = len(s)
res = [[0 for i in range(n)] for j in range(n)]
#初始条件
for i in range(n):
res[i][i] = 1
for i in range(n-1):
if s[i+1] == s[i]:
res[i][i+1] = 1
#以间隔为3开始查看
for r in range(2,n):
for l in range(r-3+1, -1, -1):
if s[l] == s[r]:
res[l][r] = res[l+1][r-1]
else:
res[l][r] = 0
#计算最长长度
val = 0
for i in range(n):
for j in range(i,n):
if res[i][j] == 1:
val = max(val,j-i+1)
return val
1. 平方串
如果一个字符串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
2. 给定一个字符串,问是否能通过添加一个字母将其变为回文串(lcstr拓展)
def justify(s):
'''思路:判断原字符串和翻转字符串的最长公共子序列长度是否比原字符串长度小1或相等'''
num = lcstr(s,s[::-1])
if num == len(s) or num == (len(s)-1):
return True
else:
return False
def lcstr(s1,s2):
m = len(s1)
n = len(s2)
res = [[0 for i in range(n+1)] for j in range(m+1)]
val = 0
for i in range(m):
for j in range(n):
if s1[i] == s2[j]:
res[i][j] = res[i-1][j-1]+1
else:
res[i][j] = 0
val = max(val, res[i][j])
return val