LCS算法
LCS即Longest Common Subsequence:最长公共子序列;
一个序列S任意删除若干个字符后得到序列T,则T叫做S的子序列,假设现在有X和Y两个序列,两者最长的公共子序列即X,Y的LCS:
比如:13455和245576的LCS为455,acdfg和adfc的LCS为adf,注意LCS要和Longest Common Substring区分开,Longest Common Substring要求char连续不能分隔开;
如何找LCS
首先想到的是暴力穷举,令X的字符数量为m,Y的字符数量为n:
X
=
{
x
1
,
.
.
.
x
m
}
X=\left \{ x_{1},...x_{m} \right \}
X={x1,...xm},
Y
=
{
y
1
,
.
.
.
y
n
}
Y=\left \{ y_{1},...y_{n} \right \}
Y={y1,...yn}
X有
2
m
2^{m}
2m个不同子序列,Y有
2
n
2^{n}
2n个不同子序列,穷举的耗时为
O
(
2
m
+
n
)
O(2^{m+n})
O(2m+n);
现在重新考虑:
X
i
=
{
x
1
,
.
.
.
x
i
}
X_{i}=\left \{ x_{1},...x_{i} \right \}
Xi={x1,...xi}为X的前i个字符,简称X的i前缀,
Y
j
Y_{j}
Yj则称为Y的j前缀,LCS(X,Y)为:
Z
=
{
z
1
,
.
.
.
z
k
}
Z=\left \{ z_{1},...z_{k} \right \}
Z={z1,...zk};
如果
x
m
=
y
n
x_{m}=y_{n}
xm=yn,则LCS(X,Y)的最后一个字符必定为
x
m
x_{m}
xm或
y
n
y_{n}
yn,即
z
k
=
x
m
=
y
n
z_{k}=x_{m}=y_{n}
zk=xm=yn,所以在这种情况下:
L
C
S
(
X
m
,
Y
n
)
=
L
C
S
(
X
m
−
1
,
Y
n
−
1
)
+
x
m
LCS(X_{m},Y_{n})=LCS(X_{m-1},Y_{n-1})+x_{m}
LCS(Xm,Yn)=LCS(Xm−1,Yn−1)+xm
如果
x
m
≠
y
n
x_{m}\neq y_{n}
xm=yn,则
L
C
S
(
X
m
,
Y
n
)
LCS(X_{m},Y_{n})
LCS(Xm,Yn)要么等于
L
C
S
(
X
m
,
Y
n
−
1
)
LCS(X_{m},Y_{n-1})
LCS(Xm,Yn−1),要么等于
L
C
S
(
X
m
−
1
,
Y
n
)
LCS(X_{m-1},Y_{n})
LCS(Xm−1,Yn),即:
L
C
S
(
X
m
,
Y
n
)
=
m
a
x
{
L
C
S
(
X
m
−
1
,
Y
n
)
,
L
C
S
(
X
m
,
Y
n
−
1
)
}
LCS(X_{m},Y_{n})=max\left \{ LCS(X_{m-1},Y_{n}),LCS(X_{m},Y_{n-1}) \right \}
LCS(Xm,Yn)=max{LCS(Xm−1,Yn),LCS(Xm,Yn−1)}
可以看出
x
m
≠
y
n
x_{m}\neq y_{n}
xm=yn时,是通过动态规划解决的
递归实现
根据前面的推理,可以通过递归实现一个函数,用来计算LCS的长度:
def recursionlcs(X,Y):
m=len(X)-1
n=len(Y)-1
#边界条件
if m<0 or n<0:
return 0
elif X[m]==Y[n]:
return recursionlcs(X[:m],Y[:n])+1
else:
return max(recursionlcs(X[:m],Y[:n+1]),recursionlcs(X[:m+1],Y[:n]))

1217

被折叠的 条评论
为什么被折叠?



