5.最长公共子序列

最长公共子序列(LeetCode 1143题 难度:中等)

第一步:dp数组定义(字符串一般是二维)

		dp[i][j]:表示S1[0,i]和S2[0,J]中最长的公共子序列的长度
		S1="ace" S2="babcde"  
		比如dp[2][4]=2的含义,就是 S1="ac"和S2=“babc”,他们的最长公共子序列就是2,根据这个答案我们需要推出  dp[3][6];

第二步:定义 base case

	专门让索引为0的行和列表示空串,dp[0][...]和dp[...][0]都初始化为 0,这就是base case (因为有一个字符串长度 是0)

第三步:状态转移方程

	两种选择:
		要么在LCS中,要么不在LCS中
	怎么知道S[i]和S[j]到底在不在LCS中???
	很容易想到,如果某个字符在LCS中,那么他必定在S1和S2中,因为LCS就是最长公共子序列
	
	dp[i][j]表示s[0到i]和s2[0到j]中的最长递增子序列,这样就可以找到状态转移关系
	如果S1[i]==S2[j],说明这个公共字符一定在lcs中,如果知道了s1[0...i-1]和s2[0...j-1]中lcs的长度,在+1 就是s1[0...i]和s2[0...j]中lcs的长度
根据dp定义得到以下逻辑
 if(s1[i]==s2[j]){
 	//转为 子问题 
 	dp[i][j]=dp[i-1][j-1]+1;
 }
	如果S1[i]!=S2[j],说明这两个字符至少有一个不在 lcs中,到底是哪个不在呢?
	我们都试一下

比如 0-6, 那么下面的意思就是:1-6 和0-5哪个公共子序列长

if(s1[i]!=s2[j]){
 	//转为 子问题 
 	dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
 }

明白了状态转移方程直接写出代码
public int longestCommonSubsequence(String text1, String text2) {  
    int m=text1.length();  
    int n=text2.length();  
    int[][] dp=new int[m+1][n+1];  
    char[] ch1 = text1.toCharArray();  
    char[] ch2 = text2.toCharArray();  
    for (int i = 1; i <= m; i++) {  
        for (int j = 1; j <=n ; j++) {  
            if(ch1[i-1]==ch2[j-1]){  
                dp[i][j]=dp[i-1][j-1]+1;  
            }else {  
                dp[i][j]=Math.max(dp[i][j-1],max(dp[i-1][j],dp[i-1][j-1]));  
            }  
        }  
    }  
    return dp[m][n];  
}
posted @ 2021-07-05 23:14  宋佳强  阅读(49)  评论(0编辑  收藏  举报