class Solution {
public:
int findLength(vector<int>& nums1, vector<int>& nums2) {
/*dp[i][j]以数字nums1[i-1]结尾的数组与以nums2[j-1]结尾的数组的最长连续公共子数组的长度
为什么不是以nums[i]和nums[j]结尾的呢,我想应该也是可以的,只是状态不太容易想到,
但是做这种二维数组的子序列子数组什么的,经验之谈一般设置数组长度都会+1,这样状态转移比较容易
"" 1 2 3 2 1
"" 0 0 0 0 0 0
3 0 0 0 1 (0) 0
2 0 0 1 0 2 0
1 0 1 0 (0) 0 3
4 0 0 0 0 0 0
7 0 0 0 0 0 0
dp[3][3]=1 nums[i]与nums[j]相等就一定是连续的公共子数组了,至少有一个
dp[1][4]=0 nums1[1]与nums2[4]不等 就一定不是连续的公共子数组
所以递推公式:dp[i][j]=dp[i-1][j-1]+1,由递推公式可知遍历应该是从dp[1][1]开始遍历的,
所以应该初始化第一行和第一列,并且是没有意义的,因为没有nums[-1]
题目要求是要求最大值,那就取二维数组的最大值就行了
*/
int m=nums1.size();
int n=nums2.size();
vector<vector<int>>dp(m+1,vector<int>(n+1));
int res=0;
for(int i=1;i<m+1;i++){
for(int j=1;j<n+1;j++){
if(nums1[i-1]==nums2[j-1]) dp[i][j]=dp[i-1][j-1]+1;
res=max(res,dp[i][j]);
}
}
return res;
}
};
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
/*dp[i][j]:以字符text[i-1]结尾的字符串与以字符text[j-1]结尾的字符串的最长公共子序列的长度
‘’ a b c d e
‘’ 0 0 0 0 0 0
a 0 1 1 1 1 1
c 0 1 1 (2) 2 2
e 0 1 1 (2) 2 3
最后一个字符相同:以上dp[2][3]=2,即字符串ac与字符串abc的最长公共子序列的长度,
他是怎么来的呢,将他们都去掉最后一个字符,
也就是之前的dp[i-1][j-1]就是字符串ab与字符串a的最长公共子序列已经算出再加上这个公共的字符
所以dp[i][j]=dp[i-1][j-1]+1;
最后一个字符不同:以上dp[3][3]=2,即字符串abc与字符串ace的最长公共子序列的长度,分三种情况
1:这两个字符都不在lcs中:dp[i][j]=dp[i-1][j-1];
2:字符text[i]在,text[j]不在:dp[i][j]=dp[i][j-1];
3:字符text[j]在,text[i]不在:dp[i][j]=dp[i-1][j];
因为要求的是最长公共子序列 在之中取最大值即:
dp[i][j]=max(dp[i-1][j],max(dp[i][j-1],dp[i-1][j-1]));
这里可以优化一下:因为两个字符都不在lsc中的长度一定是小于其中一个在的lsc中的长度
就可以去掉即dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
*/
int m=text1.size();
int n=text2.size();
vector<vector<int>>dp(m+1,vector<int>(n+1));
for(int i=1;i<m+1;i++){
for(int j=1;j<n+1;j++){
if(text1[i-1]==text2[j-1]) dp[i][j]=dp[i-1][j-1]+1;
else dp[i][j]=max(dp[i-1][j],max(dp[i][j-1],dp[i-1][j-1]));
}
}
return dp[m][n];
}
};