描述
给定两个字符串str1和str2,输出两个字符串的最长公共子序列。如果最长公共子序列为空,则返回"-1"。目前给出的数据,仅仅会存在一个最长的公共子序列
数据范围: 0≤∣str1∣,∣str2∣≤2000
要求:空间复杂度 O(n2) ,时间复杂度 O(n2)
示例1
输入:
"1A2C3D4B56","B1D23A456A"
返回值:
"123456"
示例2
输入:
"abc","def"
返回值:
"-1"
示例3
输入:
"abc","abc"
返回值:
"abc"
示例4
输入:
"ab",""
返回值:
"-1"
dp 背包题
建立二维数组,记录字符到该位置的最大长度,例如字符串 s1 = SDSF 和 s2 = ASDF
S | D | S | F | |
A | 0 | 0 | 0 | 0 |
S | 1 | 1 | 1 | 1 |
D | 1 | 2 | 2 | 2 |
F | 1 | 2 | 2 | 3 |
数组建立逻辑
1、初始化第一行,将 A 与 s1 中逐一对比
2、初始化第一列,将 S 与 s2 逐一对比,结果val与 dp[yPos-1][xPos] 取最大值
3、每一个位置,如果字符相同,那这个点的值就是 dp[yPos-1][xPos-1] + 1。如果字符不相同,那这个点的值就是 Max(dp[yPos-1][xPos], dp[yPos][xPos-1])
4、从最后一行获取长度最大值,从该点开始搜索,每个点横向纵向把相同值全都走掉,记录最后点,然后 yPos-- xPos--,重复上述操作,直到边界。
S | D | S | F | |
A | 0 | 0 | 0 | 0 |
S | 1 | 1 | 1 | 1 |
D | 1 | 2 | 2 | 2 |
F | 1 | 2 | 2 | 3 |
public String LCS (String s1, String s2) {
// write code here
if (s1 == null || s2 == null || s1.isEmpty() || s2.isEmpty()) {
return "-1";
}
int length1 = s1.length();
int length2 = s2.length();
if (length1 == 1 && s1.equals(s2)) {
return s1;
}
int xPos;
int yPos;
int[][] dpMap = new int[length2][length1];
int maxValue = 0;
// 初始化数组
for (xPos = 0; xPos < length1; xPos++) {
char c = s2.charAt(0);
if (c == s1.charAt(xPos)) {
maxValue = 1;
}
dpMap[0][xPos] = maxValue;
}
maxValue = 0;
for (yPos = 0; yPos < length2; yPos++) {
char c = s1.charAt(0);
if (c == s2.charAt(yPos)) {
maxValue = 1;
}
dpMap[yPos][0] = maxValue;
}
// 背包字符串
for (yPos = 1; yPos < length2; yPos++) {
char c = s2.charAt(yPos);
for (xPos = 1; xPos < length1; xPos++) {
if (c == s1.charAt(xPos)) {
dpMap[yPos][xPos] = dpMap[yPos-1][xPos-1] + 1;
} else {
dpMap[yPos][xPos] = Math.max(dpMap[yPos-1][xPos], dpMap[yPos][xPos-1]);
}
}
}
maxValue = -1;
int maxPos = 0;
// 找到最长串末尾
for (xPos = 0; xPos < length1; xPos++) {
if (maxValue < dpMap[length2-1][xPos]) {
maxValue = dpMap[length2-1][xPos];
maxPos = xPos;
}
}
if (maxValue == 0) {
return "-1";
}
xPos = maxPos;
yPos = length2 - 1;
char[] resultArray = new char[maxValue];
maxValue--;
while (xPos > 0 && yPos > 0 && maxValue >= 0) {
if (dpMap[yPos-1][xPos] == dpMap[yPos][xPos]) {
// 向上走到头
for (; yPos > 0; yPos--) {
if (dpMap[yPos-1][xPos] != dpMap[yPos][xPos]) {
break;
}
}
}
if (dpMap[yPos][xPos-1] == dpMap[yPos][xPos]) {
// 向左走到头
for(; xPos > 0; xPos--) {
if (dpMap[yPos][xPos-1] != dpMap[yPos][xPos]) {
break;
}
}
}
resultArray[maxValue--] = s1.charAt(xPos);
xPos--;
yPos--;
}
if (maxValue == 0) {
if (yPos > 0 && dpMap[yPos-1][xPos] == dpMap[yPos][xPos]) {
// 向上走到头
for (; yPos > 0; yPos--) {
if (dpMap[yPos-1][xPos] != dpMap[yPos][xPos]) {
break;
}
}
}
if (xPos > 0 && dpMap[yPos][xPos-1] == dpMap[yPos][xPos]) {
// 向左走到头
for(; xPos > 0; xPos--) {
if (dpMap[yPos][xPos-1] != dpMap[yPos][xPos]) {
break;
}
}
}
resultArray[0] = s1.charAt(xPos);
}
return new String(resultArray);
}