✅ tips
1.考虑空串,即dp表多出一行一列, 代表某个字符串为空。
2.考虑最后一个位置;是否相等;
3.可在字符串最前面加虚拟位置以对应映射关系;
4.一般横行是j,列是i。此时第一行代表第二个字符串不为空,即第一个字符串是空的
1.最长公共子序列
class Solution {
//dp[i][j]表s1的[0,i]以及s2的[0,j]所有子序列中最长公共子序列的长度;
//如果s[i]=s[j],那公共序列一定是以i,j为结尾
public int longestCommonSubsequence(String s1, String s2) {
int m = s1.length(), n = s2.length();
s1 = " " + s1;
s2 = " " + s2;
int[][] dp = new int[m + 1][n + 1];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s1.charAt(i) == s2.charAt(j)) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[m][n];
}
}
//!=时,有[0,i-1]&[0,j],[0,i-1]&[0,j-1],[0,i]&[0,j-1];空串
StringBuilder sb = new StringBuilder();
int i = m, j = n;
while (i > 0 && j > 0) {
if (s1.charAt(i) == s2.charAt(j)) {
sb.insert(0, s1.charAt(i));
i--;
j--;
} else if (dp[i - 1][j] >= dp[i][j - 1]) {
i--;
} else {
j--;
}
}
System.out.println( sb.toString());
2.最长重复子数组
class Solution {
public int findLength(int[] nums1, int[] nums2) {
int m=nums1.length;int n=nums2.length;
int[][] dp=new int[m+1][n+1];
int ret=0;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(nums1[i-1]==nums2[j-1])
dp[i][j]=dp[i-1][j-1]+1;
ret=Math.max(ret,dp[i][j]);
}
}
return ret;
}
}
class Solution {
public int[] findLength(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
int[][] dp = new int[m + 1][n + 1];
int maxLength = 0;
int endIndex = 0;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (nums1[i - 1] == nums2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;