LintCode刷题笔记-- LongestCommonSquence
标签:动态规划
题目描述:
Given two strings, find the longest common subsequence (LCS).
Your code should return the length of LCS.
解题思路:
这一题是非常经典的动态规划问题,在解题思路上可以按照经典的动态规划的解法,这是在系统学习动态规划之后第一个解决的LintCode上的问题:
1.子问题划分
给出两个字符串的A,B,两个字符串长度分别为lenA,lenB,求出两个字符串的LCS:
这划分为子问题:A.subString(0,0) 与B的LCS,在此基础上A.subString(0,1)与B的LCS,依次类推,可以得到A.subString(0,lenA-2), A.subString(0,lenA-1) 与B的LCS。 按照A的方法也同样可以对B在长度上进行分解。这样可以形成字符串A与B长度为lenA*lenB的矩阵,此矩阵为记录状态的“备忘录”。
2.初始状态的定义
对于LCS矩阵的初始状态,对于第一行与第一列相对应的意义为,A与B的第一个元素作为一个长度为1的字符串与对方是否存在公共字符,若存在,所在位置坐标已经后续坐标全部置为1.
3.问题与子问题解的关系
dp[i][j]:字符串的A的子串dp(0,i)与字符串B的子串dp(0,j)之间LCS的长度
dp[i][j]的取值:当A[i] == B[j],A(0,i)与B(0,j)之间的LCS会较比A(0,i-1)与B(0,j-1)多1,因为多了1位公共字符,LCS的长度自然会增加1。
当A[i]!=B[j], A(0,i)与B(0,j)之间的LCS会选择先前公共子串更多的部分作为下一步求解
4.边界条件
当达到A,B两者的最大长度时结束
5.参考代码:
1 public int longestCommonSubsequence(String A, String B) { 2 int lenA = A.length(); 3 int lenB = B.length(); 4 5 if(lenA == 0 || lenB == 0){ 6 return 0; 7 } 8 9 int[][] dp = new int[lenA][lenB]; 10 11 if(A.charAt(0)==B.charAt(0)){ 12 dp[0][0] = 1; 13 } 14 15 for(int i = 1; i < lenA; i++){ 16 if(B.charAt(0)==A.charAt(i)){ 17 dp[i][0] = 1; 18 }else{ 19 dp[i][0] = dp[i-1][0]; 20 } 21 } 22 for(int j = 1; j < lenB; j++){ 23 if(A.charAt(0)==B.charAt(j)){ 24 dp[0][j] = 1; 25 }else{ 26 dp[0][j] = dp[0][j-1]; 27 } 28 } 29 30 31 for(int i = 1; i<lenA; i++){ 32 for(int j = 1; j<lenB; j++){ 33 dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]); 34 if(A.charAt(i) == B.charAt(j)){ 35 dp[i][j] = dp[i-1][j-1]+1; 36 } 37 38 39 } 40 } 41 return dp[lenA-1][lenB-1]; 42 }