力扣[剑指 Offer II 095. 最长公共子序列]
题目:
思路:
动态规划,定义一个大小为 m , n m,n m,n的二维数组
定义 d p i j dp_{ij} dpij为 s 1 s1 s1字符串前 i i i个字符与 s 2 s2 s2字符串前 j j j个字符的最长公共子序列
不难发现当 i = 0 ∣ j = 0 i=0|j=0 i=0∣j=0时, d p i , j dp_{i,j} dpi,j一定等于 0 0 0
刚好数组初始化所有之都为 0 0 0,所以我们从 i = 1 , j = 1 i=1,j=1 i=1,j=1开始循环查表
对于每一个 d p i , j dp_{i,j} dpi,j它的值都为前面所有可能的状态的最大值
加上当前值:
每个
d
p
i
,
j
dp_{i,j}
dpi,j首先判断当前字符加不加 如果
s
1
[
i
]
=
=
s
2
[
j
]
s1[i]==s2[j]
s1[i]==s2[j],那么加上当前的
i
,
j
i,j
i,j,值应该为
d
p
[
i
]
[
j
]
=
d
p
[
i
−
1
]
[
j
−
1
]
+
1
dp[i][j]=dp[i-1][j-1]+1
dp[i][j]=dp[i−1][j−1]+1
因为我们已经算上了
s
1
[
i
]
=
=
s
2
[
j
]
s1[i]==s2[j]
s1[i]==s2[j]的公共串,并且加一了,所以我们再加上
d
p
[
i
−
1
]
[
j
−
1
]
dp[i-1][j-1]
dp[i−1][j−1]的值就是加当前字符的值
不加上当前值
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
−
1
]
[
j
]
,
d
p
[
i
]
[
j
−
1
]
)
dp[i][j]=max(dp[i-1][j],dp[i][j-1])
dp[i][j]=max(dp[i−1][j],dp[i][j−1])
所以我们只需要对两种状态取最大值就是我们当前
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]的值
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
−
1
]
[
j
−
1
]
+
m
a
r
k
,
m
a
x
(
d
p
[
i
−
1
]
[
j
]
,
d
p
[
i
]
[
j
−
1
]
)
)
m
a
r
k
为
状
态
位
,
如
果
s
1
[
i
]
=
=
s
2
[
j
]
,
那
么
m
a
r
k
=
1
,
否
则
m
a
r
k
=
0
dp[i][j]=max(dp[i-1][j-1]+mark,max(dp[i-1][j],dp[i][j-1]))\\ mark为状态位,如果s1[i]==s2[j],那么mark=1,否则mark=0
dp[i][j]=max(dp[i−1][j−1]+mark,max(dp[i−1][j],dp[i][j−1]))mark为状态位,如果s1[i]==s2[j],那么mark=1,否则mark=0
代码:
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int len1=text1.size();
int len2=text2.size();
text1='@'+text1;
text2='@'+text2;//使有效值的下标从1开始
int dp[1010][1010]={0};
for(int i=1;i<=len1;i++){
for(int o=1;o<=len2;o++){
int mark=0;
if(text1[i]==text2[o]){
mark++;
}
dp[i][o]=max(dp[i-1][o-1]+mark,max(dp[i-1][o],dp[i][o-1]));
}
}
return dp[len1][len2];
}
};