描述
给定两个字符串str1和str2,输出两个字符串的最长公共子序列。如果最长公共子序列为空,则返回"-1"。目前给出的数据,仅仅会存在一个最长的公共子序列
数据范围:0≤∣str1∣,∣str2∣≤20000 \le |str1|,|str2| \le 20000≤∣str1∣,∣str2∣≤2000
要求:空间复杂度 O(n2)O(n^2)O(n2) ,时间复杂度 O(n2)O(n^2)O(n2)
示例1
输入:“1A2C3D4B56”,“B1D23A456A”
返回值:“123456”
示例2
输入:“abc”,“def”
返回值: “-1”
示例3
输入:
“abc”,“abc”
返回值:“abc”
示例4
输入: “ab”,“”
返回值: “-1”
思路:
题目要求获取最长公共子序列,我们肯定要先知道最长到底是多长,因此肯定要先求最长公共子序列的长度,然后根据这个长度获取这个子序列。(注意:子序列不是子串,子串要求所有字符必须连续,子序列不要求连续,只要求相对位置不变)
import java.util.*;
public class Solution {
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
/**
先看阿拉伯数字,再看中文数字
*/
//3.1定义私有的字符串x、y,并初始化
private String x="";
private String y="";
//二、获取最长公共子序列,c参数为整型i,j,二维数组b
String ans(int i, int j, int[][] b) {
//三、定义字符串类型的结果集res,并初始化
String res = "";
//四、递归终止条件(如果i,j为0,直接返回结果集)
if (i == 0 || j == 0)
return res;
//五、根据方向(左上方、左方、上方)、往前递归,然后添加本级字符
if (b[i][j] == 1) {
res += ans(i-1, j-1, b);
//五.一 从x中添加本级字符
res += x.charAt(i - 1);
} else if (b[i][j] == 2)
res += ans(i - 1, j, b);
else if (b[i][j] == 3)
res += ans(i, j - 1, b);
//六、最后返回结果集res
return res;
}
public String LCS (String s1, String s2) {
// write code here
//1.优先检查特殊情况(如果s1或s2长度为0时,返回字符串-1)
if (s1.length() == 0 || s2.length() == 0)
return "-1";
//2.获取s1、s2的长度赋值给len1、len2
int len1 = s1.length();
int len2 = s2.length();
//3.2定义字符串x、y后,将s1、s2分别复制给x,y
x = s1;
y = s2;
//4.首先获取最长公共子序列的长度(使用动态规划)
//5.整型二维数组dp[i][j]表示第一个字符串到第i位,第二字符串到第j位为止的最长公共子序列长度
int[][] dp = new int[len1 + 1][len2 + 1];
//6.动态规划数组相加的方向
int[][] b = new int[len1 + 1][len2 + 1];
//7.双层for循环遍历两个字符串每个位置求最长长度
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
//8.s1、s2两个字符串遇到两个字符相等
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
//9.考虑由二者都向前一位
dp[i][j] = dp[i - 1][j - 1] + 1;
//10.来自于左上方(左上方为1)
b[i][j] = 1;
}
else {
//11.遇到的两个字符不同(charAt())
//12.如果(if)左边的选择更大,即第一个字符串后退一位
if (dp[i - 1][j] > dp[i][j - 1]) {
dp[i][j] = dp[i - 1][j];
//13.来自于左方(左方为2)
b[i][j] = 2;
} else {
//14.右边的选择更大,即第二字符串后退一位
dp[i][j] = dp[i][j - 1];
//15.来自于上方(上方为3)
b[i][j] = 3;
}
}
}
}
//一、获取答案字符串string
String res = ans(len1, len2, b);
//六、检查答案是否为空,如果为空则返回-1,否则返回结果集res
if (res.isEmpty())
return "-1";
else
return res;
}
}