第二种:动态规划
思路: 二维数组, 下图:str1: sabgc ,s2:abcg, 二维数组,相同的标记为1 ,不同的标0,可以看出斜对角为1 的就是最长的字串。第一个一样标记1, 第二个对角相同,值应该是x,y下标-1 的值在+1,记录的就是长度。
为了让递推公式dp[i][j] = dp[i-1][j-1] + 1;成立,所以应多初始化一行一列dp[0][0],相当于在图片外层又包裹一行一列的0
红色部分为新增的一行一列的初始化dp
黄色部分为数组下标偏移1位
这样在推到dp[1][0]的时候 就可以通过刚刚新增的dp初始化红色部分数组的值0,来推出其值为左上角位置+1
import java.util.*;
public class Solution {
/**
* longest common substring
* @param str1 string字符串 the string
* @param str2 string字符串 the string
* @return string字符串
*/
public String LCS (String str1, String str2) {
if (str1 == null || str2 == null || str1.length() == 0 || str2.length() == 0) {
return "-1";
}
//动态规划 二维数组,斜下来就是最长字串
int str1Len = str1.length();
int str2Len = str2.length();
//记录最长公共子串长度
int maxLen = 0;
//记录最长子串最后一个字符的下标
int index = 0;
//这里+1 是为了让dp[i][j] = dp[i-1][j-1] + 1;递推公式成立,单独多出一行一列dp[0][0]供递推公式计算
int[][] dp = new int[str1Len + 1][str2Len + 1];
//str1为行坐标
for (int i = 1; i <= str1Len; i++) {
//str2为列坐标
for (int j = 1; j <= str2Len; j++) {
//这里的i-1 j-1意味着是字符串的第一个字符,而非dp[0][0]这个第一列
if (str1.charAt(i-1) == str2.charAt(j-1)) {
//str1 str2的该位置字符如果相等,那么用上一个斜上角位置的元素进行+1 可获取当前公共子串的长度
dp[i][j] = dp[i-1][j-1] + 1;
} else {
dp[i][j] = 0;
}
if (maxLen < dp[i][j]) {
maxLen = dp[i][j];
//因为不能算dp[0] 所以以上循环都是从1开始的 这里要减去1
index = i-1;
}
}
}
if (maxLen == 0) {
return "-1";
}
return str1.substring(index - maxLen + 1, index + 1);
}
} 


京公网安备 11010502036488号