【题目详情】
给定两个字符串str1和str2,输出连个字符串的最长公共子序列。如过最长公共子序列为空,则输出-1。具体见牛客官网,首页 > 在线编程 > 程序员代码面试指南查看提交。链接直达
【输入描述】
输出包括两行,第一行代表字符串str1,第二行代表str2。
(1≤length(str1),length(str2)≤5000)
【输出描述】
输出一行,代表他们最长公共子序列。如果公共子序列的长度为空,则输出-1。
【复杂度】
- 时间复杂度O(n*m)O(n∗m)
- 空间复杂度O(n*m)O(n∗m)。(n,m分别表示两个字符串长度)
【完整代码】
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str1 = sc.next();
String str2 = sc.next();
System.out.println(lcse(str1, str2));
}
public static int[][] getdp(String str1, String str2)
{
int[][] dp = new int[str1.length()][str2.length()];
char[] str1Arr = str1.toCharArray();
char[] str2Arr = str2.toCharArray();
dp[0][0] = str1Arr[0] == str2Arr[0] ? 1 : 0 ;
for(int i = 1; i < str1.length(); i++)
{
//第零列
dp[i][0] = Math.max(dp[i-1][0], (str1Arr[i] == str2Arr[0] ? 1 : 0));
}
for(int j = 1; j < str2.length(); j++)
{
//第零行
dp[0][j] = Math.max(dp[0][j-1], (str1Arr[0] == str2Arr[j] ? 1 : 0));
}
for(int i = 1; i < str1.length(); i++)
{
for(int j = 1; j < str2.length(); j++)
{
//先比较左和上,取大者
dp[i][j] = Math.max(dp[i][j-1], dp[i-1][j]);
if(str1Arr[i] == str2Arr[j])
{
dp[i][j] = Math.max(dp[i-1][j-1]+1, dp[i][j]);
}
}
}
return dp;
}
public static String lcse(String str1, String str2)
{
int m = str1.length()-1;
int n = str2.length()-1;
int[][] dp = new int[m+1][n+1];
dp = getdp(str1, str2);
char[] res = new char[dp[m][n]];
char[] str1Arr = str1.toCharArray();
char[] str2Arr = str2.toCharArray();
if(str1 == null || str2 == null || str1.equals("") || str2.equals("") || dp[m][n] == 0)
{
return "-1";
}
int index = res.length - 1;
//比如res数组长度为7,实际计算过程并不是7次,而是大于等于7次
while(index >= 0)
{
if(n > 0 && dp[m][n] == dp[m][n-1])//来自左
{
n--;
}
else if(m > 0 && dp[m][n] == dp[m-1][n])//来自上
{
m--;
}
else
{
//dp[m][n] == dp[m-1][n-1] + 1 || dp[0][n] == dp[0][n-1] + 1 || dp[m][0] == dp[m-1][0] + 1
res[index--] = str1Arr[m];
m--;
n--;
}
}
return String.valueOf(res);
}
}