难度:中等
频次:64
**题目:**给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。
一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
- 例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。
解题思路:动态规划
注意: - 为什么是动态规划?—>求最值,并且都跟前面的值有关。并且之前求过最长有序子串就是用的动态规划
- 这里的起始值 是dp[0][1] dp[0][1] dp[0][0]都等于0,代表的意思就是只要出现一个空字符串,最后的最值都为0
- 两个for循环都是从1开始的,并且dp[i][j]代表的是第一个字符串的前i个和第二个字符串的前j个的最长公共子串,i和j的取值是从0-n和0-m(n、m分别表示两个字符串的长度)
- 两个转移转移方程
- 第一个条件是最后的两个元素相等 dp[i][j]=d[i-1][j-1]+1;
- 第二个条件是最后的两个元素不相等 那么就把一个拆成两个求解,并且取大值。
dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1])
代码:
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int n=text1.length(),m=text2.length();
//new int 需要注意,并且我们dp是从1开始的
//为什么是从1开始的?很多人说这样子比较方便
//但实际上是由状态转移方程决定的,因为跟之前的有关。所以这里必须长度多1个,再加上我们思维是从1开始的
int[][] dp=new int[n+1][m+1];//dp[i][j] 代表的是第一个长度为i,第二个长度为j的最长公共子串长度
//这里的最初状态其实时dp[1][0]=0, dp[1][0]这里就不写了
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
//状态转移方程主要有两条
if(text1.charAt(i-1)==text2.charAt(j-1)){
//如果最后两个元素相等,那么整体的dp=去掉相等元素的dp值+1
dp[i][j]=dp[i-1][j-1]+1;
}else{
//如果不不相等,就把一个拆成2个求解,最后取两个里的最大值即可
dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[n][m];
}
}