给定两个字符串str1和str2,输出两个字符串的最长公共子序列。如果最长公共子序列为空,则返回"-1"。目前给出的数据,仅仅会存在一个最长的公共子序列
数据范围:
要求:空间复杂度
,时间复杂度
"1A2C3D4B56","B1D23A456A"
"123456"
"abc","def"
"-1"
"abc","abc"
"abc"
"ab",""
"-1"
function LCS( s1 , s2 ) {
if (s1.length > s2.length) [s1, s2] = [s2, s1];
const dp = new Array(s2.length + 1).fill('');
for (let i = 1; i <= s1.length; i++) {
let pre = '';
for (let j = 1; j <= s2.length; j++) {
const tmp = dp[j];
if (s1[i - 1] === s2[j - 1]) dp[j] = pre + s2[j - 1];
else dp[j] = dp[j].length > dp[j - 1].length ? dp[j] : dp[j - 1];
pre = tmp;
}
}
const res = dp[s2.length];
return res === '' ? '-1' : res;
}
class Solution {
public:
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
string LCS(string s1, string s2) {
// write code here
string ans = "";
int len1 = s1.size(), len2 = s2.size();
vector<vector<int> > dp(len1, vector<int>(len2, 0));
for(int i=0; i<len1; ++i) {
for(int j=0; j<len2; ++j) {
if(i == 0 || j == 0) dp[i][j] = s1[i] == s2[j] ? 1 : 0;
else {
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
if(s1[i] == s2[j]) {
dp[i][j] = dp[i-1][j-1] + 1;
}
}
}
}
int row = len1-1;
int col = len2-1;
while(col >=0 && col >=0 ) {
if(row-1 >= 0 && col-1 >= 0 && dp[row-1][col-1] == dp[row][col]+1){
ans+=s1[row];
col--;
row--;
}else if(row-1>=0 && dp[row-1][col] == dp[row][col]){
row--;
}else if(col-1>=0 && dp[row][col-1] == dp[row][col]) {
col--;
}else { // 到达边界,退出
break;
}
}
return ans;
}
}; import java.util.*;
public class Solution {
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
public String LCS (String s1, String s2) {
int n1=s1.length(),n2=s2.length();
String[][]dp=new String[n1+1][n2+1];//表示当处理到s1的第i个元素和s2的第j个元素时公共子序列的长度
for(int i=0;i<=n1;i++){
for(int j=0;j<=n2;j++){
if(i==0||j==0) dp[i][j]="";
else if(s1.charAt(i-1)==s2.charAt(j-1)){//如果相同的话
// dp[i][j]=dp[i-1][j-1]+1;
dp[i][j]=dp[i-1][j-1]+s1.charAt(i-1);
}
else {
// dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
dp[i][j]=dp[i-1][j].length()>dp[i][j-1].length()?dp[i-1][j]:dp[i][j-1];
}
}
}
if(dp[n1][n2]=="") return "-1";
return dp[n1][n2];
}
}
class Solution {
public:
string LCS(string s1, string s2) {
// write code here
string dp[s1.size()+1][s2.size()+1];
for(int i=0;i<=s1.size();i++)
dp[i][0] = "";
for(int i=0;i<=s2.size();i++)
dp[0][i] = "";
for(int i=1;i<=s1.size();i++){
for(int j=1;j<=s2.size();j++){
if(s1[i-1]==s2[j-1]) dp[i][j] = dp[i-1][j-1]+s1[i-1];
else{
dp[i][j] = dp[i-1][j].size()>dp[i][j-1].size()?dp[i-1][j]:dp[i][j-1];
}
}
}
return dp[s1.size()][s2.size()]==""?"-1":dp[s1.size()][s2.size()];
}
}; class Solution {
public:
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
string LCS(string s1, string s2) {
int len1 = s1.length() + 1;
int len2 = s2.length() + 1;
string res = "";
vector<vector<int> > dp(len1, vector<int>(len2, 0));
for (int i = 1; i < len1; ++i)
for (int j = 1; j < len2; ++j)
if (s1[i - 1] == s2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
int i = len1 - 1, j = len2 - 1;
while (dp[i][j]) {
if (dp[i-1][j] == dp[i][j-1] && dp[i][j] > dp[i-1][j-1]) {
res += s1[i - 1];
--i;
--j;
}
else if (dp[i - 1][j] > dp[i][j - 1]) --i;
else --j;
}
reverse(res.begin(), res.end());
return res;
}
}; for (auto i : dp) { for (auto j : i) cout << j << ' '; cout << endl; } /* 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 2 2 2 2 2 2 0 0 1 1 2 2 2 2 2 2 2 2 2 0 0 1 1 2 2 3 3 3 3 3 3 3 0 0 1 1 2 3 3 3 3 3 3 3 3 0 0 1 2 2 3 3 3 3 3 3 3 3 0 0 1 2 2 3 3 3 4 4 4 4 4 0 1 1 2 2 3 3 3 4 4 5 5 5 0 1 1 2 2 3 3 3 4 5 【5】 5 5 0 1 1 2 2 3 3 3 4 5 5 6 6 */
dp[i-1][j] == dp[i][j-1] && dp[i][j] > dp[i-1][j-1] //前者表示不是取子序列较长者,而是当前位置字符相等 //后者是为了区别有多个公共序列等长,注意分析dp数组中括起来的部分
else if (dp[i - 1][j] > dp[i][j - 1]) --i;
else if (dp[i - 1][j] >= dp[i][j - 1]) --i;答案是:123456
class Solution: def LCS(self , s1 , s2 ): # write code here m, n = len(s1), len(s2) dp = [[''] * (n + 1) for _ in range(m + 1)] for i in range(1, m + 1): for j in range(1, n + 1): if s1[i - 1] == s2[j - 1]: dp[i][j] = dp[i - 1][j - 1] + s1[i - 1] else: if len(dp[i - 1][j])>len(dp[i][j - 1]): dp[i][j] =dp[i - 1][j] else: dp[i][j] =dp[i][j - 1] if dp[m][n]=='': return -1 else: return dp[m][n]
class Solution(object): def longestCommonSubsequence(self, text1, text2): """ :type text1: str :type text2: str :rtype: int """ m, n = len(text1), len(text2) dp = [[0] * (n + 1) for _ in range(m + 1)] for i in range(1, m + 1): for j in range(1, n + 1): if text1[i - 1] == text2[j - 1]: dp[i][j] = dp[i - 1][j - 1] + 1 else: dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) return dp[m][n]
class Solution {
public:
string LCS(string s1, string s2) {
int sz1 = s1.size();
int sz2 = s2.size();
string res;
// 动态规划获取dp矩阵
vector<vector<int>> dp(sz1 + 1, vector<int>(sz2 + 1));
for (int i = 1; i <= sz1; ++i)
for (int j = 1; j <= sz2; ++j)
if (s1[i-1] == s2[j-1])
dp[i][j] = dp[i-1][j-1] + 1;
else
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
// 取得左上角的字符
int trace = dp[sz1][sz2];
int i = sz1, j = sz2;
while (trace) {
if (dp[i-1][j] == trace) --i;
else if (dp[i][j-1] == trace) --j;
else {
res.push_back(s1[i-1]);
--trace;
--i;
--j;
}
}
// 双指针翻转字符串
int sz = res.size();
for (int k = 0; k < sz / 2; ++k) {
auto temp = res[sz - 1 - k];
res[sz - 1 - k] = res[k];
res[k] = temp;
}
return res.empty() ? "-1" : res;
}
}; class Solution:
def LCS(self , s1: str, s2: str) -> str:
if s1 is None or s2 is None:
return '-1'
len1 = len(s1)
len2 = len(s2)
dp = [[''] * (len2 + 1) for i in range(len1 + 1)]
for i in range(1, len1+1):
for j in range(1, len2+1):
if s1[i-1] == s2[j-1]:
dp[i][j] = dp[i-1][j-1] + s1[i -1]
else:
dp[i][j] = dp[i][j-1] if len(dp[i][j-1]) > len(dp[i-1][j]) else dp[i-1][j]
return dp[-1][-1] if dp[-1][-1] != '' else '-1'
class Solution {
public:
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
string LCS(string s1, string s2) {
// write code here
int m = s1.length();
int n = s2.length();
if (m == 0 || n == 0)
return "-1";
vector<vector<string>> dp(2, vector<string>(n + 1, ""));
int row = 1;
for (int i = 1; i <= m; i++)
{
row = 1 - row;
for (int j = 1; j <= n; j++)
{
if (s1[i - 1] == s2[j - 1])
dp[row][j] = dp[1- row][j - 1] + s1[i - 1];
else
{
if (dp[row][j - 1].length() >= dp[1- row][j].length())
dp[row][j] = dp[row][j - 1];
else
dp[row][j] = dp[1 - row][j];
}
}
}
return dp[row][n] == "" ? "-1" : dp[row][n];
}
}; import java.util.*;
public class Solution {
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
public String LCS (String s1, String s2) {
// write code here
int m = s1.length(), n = s2.length();
int[][] dp = new int[m + 1][n + 1];
for (int i = 1; i < m + 1; i ++) {
for (int j = 1; j < n + 1; j ++) {
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else if (dp[i][j - 1] > dp[i - 1][j]) {
dp[i][j] = dp[i][j - 1];
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
if (dp[m][n] == 0) return "-1";
int length = dp[m][n];
StringBuffer lcs = new StringBuffer();;
while (true) {
if (s1.charAt(m - 1) == s2.charAt(n - 1)) {
lcs.insert(0, s1.charAt(m - 1));
length -- ;
if (length <= 0) break;
m --;
n--;
} else if (dp[m - 1][n] > dp[m][n - 1]) {
m --;
} else {
n --;
}
}
return lcs.toString();
}
} import java.util.*;
public class Solution {
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
public String LCS (String s1, String s2) {
// write code here
int length1 = s1.length();
int length2 = s2.length();
StringBuffer[][] dp = new StringBuffer[length1 + 1][length2 + 1];
for (int i = 0; i <= length1; i++) {
dp[i][0] = new StringBuffer();
}
for (int i = 0; i <= length2; i++) {
dp[0][i] = new StringBuffer();
}
for (int i = 1; i <= length1; i++) {
for (int j = 1; j <= length2; j++) {
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
dp[i][j] = new StringBuffer(dp[i - 1][j - 1]);
dp[i][j].append(s1.charAt(i - 1));
} else {
dp[i][j] = new StringBuffer(dp[i - 1][j].length() > dp[i][j - 1].length() ? dp[i - 1][j] : dp[i][j - 1]);
}
}
if (i > 1) {
for (int j = 0; j <= length2; j++) {
dp[i - 2][j] = null; // 清除内存
}
}
}
if (dp[length1][length2].length() == 0) {
dp[length1][length2].append(-1);
}
return dp[length1][length2].toString();
}
} import java.util.*;
public class Solution {
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
public String LCS (String s1, String s2) {
// write code here
int m = s1.length(), n = s2.length();
int[][] dp = new int[m][n];
StringBuilder res = new StringBuilder();
//动态规划找到最长公共子序列
for(int i = 0; i < m;i++){
for(int j = 0; j < n;j++){
if(i==0 || j==0){
dp[i][j] = 0;
}
else{
if(s1.charAt(i) == s2.charAt(j))
dp[i][j] = dp[i-1][j-1] + 1;
else
dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
int i = m-1, j = n-1;
while(i >= 0 && j >= 0){
if(s1.charAt(i) == s2.charAt(j)){
res.append(s1.charAt(i));
i--;
j--;
}
if(i>0 && j>0 && s1.charAt(i) != s2.charAt(j)){
if(dp[i-1][j] > dp[i][j-1])
i--;
else
j--;
//dp[i-1][j] < dp[i][j-1]时,j--;
//dp[i-1][j] = dp[i][j-1]时,i--或j--,这里统一为j--;
}
//行或列到达边界
if(i==0)j--;
if(j==0)i--;
}
if(res.toString().equals("") || res==null)return "-1";
return res.reverse().toString();
}
} public static String LCS (String s1, String s2) {
int length1 = s1.length();
int length2 = s2.length();
int[][] dp = new int[length1+1][length2+1];
char[][] dp2 = new char[length1+1][length2+1];
for (int i = 1; i <= length1; i++) {
for (int j = 1; j <= length2; j++) {
if(s1.charAt(i-1)==s2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1]+1;
dp2[i][j] = s1.charAt(i-1);
}else{
dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
StringBuilder sb = new StringBuilder();
int a = length1;
int b = length2;
for (int i =dp[length1][length2]; i >0 ; i--) {
boolean flag = false;
for (int j = a; j >=1 ; j--) {
for (int k = b; k >=1; k--) {
if(dp[j][k]==i && dp2[j][k]!=0 ){
sb.append(dp2[j][k]);
a = j;
b = k;
flag = true;
break;
}
}
if(flag){
break;
}
}
}
return sb.reverse().toString();
} public class Solution {
public String LCS (String s1, String s2) {
// 字符串1的长度
int sLen1 = s1.length();
// 字符串2的长度
int sLen2 = s2.length();
// dp数组,初始化高度和宽度分别为两个字符串长度+1
// 目的是方便初始化,如果高度和宽度分别是两个字符串的长度,初始化会比较麻烦
// s1[0,i)和s2[0,j)所构成的最长子序列是dp[i][j]
String[][] dp = new String[sLen1 + 1][sLen2 + 1];
// dp数组初始化
for (int i = 0; i <= sLen1; i++) {
dp[i][0] = "";
}
for (int j = 0; j <= sLen2; j++) {
dp[0][j] = "";
}
// 遍历每一种情况
for (int i = 1; i <= sLen1; i++) {
for (int j = 1; j <= sLen2; j++) {
// 因为长度和宽度都是字符串长度+1,所以这里取字符的时候需要减1,保证不越界
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
// 因为要加入的两个字符一样,所以直接取两个字符加入前的最长公共子序列然后加上这个相等的字符
dp[i][j] = dp[i - 1][j - 1] + s1.charAt(i - 1);
} else {
// 取s1不加入当前字符和s2不加入当前字符的情况中的最长的那个子序列
if (dp[i - 1][j].length() >= dp[i][j - 1].length()) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = dp[i][j - 1];
}
}
}
}
return "".equals(dp[sLen1][sLen2]) ? "-1" : dp[sLen1][sLen2];
}
} //状态压缩,动态规划
class Solution {
public:
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
string LCS(string s1, string s2) {
int m = s1.size();
int n= s2.size();
//实际只用到 要求位置的 上(dp[i-1][j]) ,左上(dp[i-1][j-1]), 左(dp[i][j-1]) 这三个值 用2行状态压缩;
//只用1行的话 前向后遍历先更新 左 会覆盖 左上 的值 。。
// 还有一个用的2行 0行1行来回滚动 绕晕了。。。 这里就 更新一行还好理解一点
vector<vector<string>>dp(2,vector<string>(n+1));
for(int i= 1;i<=m;i++)
{
for(int j= 1;j<=n;j++)
{
if(s1[i-1]==s2[j-1])
dp[1][j]=dp[0][j-1] + s1[i-1]; //只更新dp第2行 ,包括 左 的值
else
dp[1][j]=dp[0][j].size() > dp[1][j-1].size()?dp[0][j]:dp[1][j-1];
}
for(int k=0;k<=n;k++)
dp[0][k]=dp[1][k]; // 把1行的值赋值给dp的0行 来保存 上 ,左上 这两个位置
}
return dp[1][n]==""?"-1":dp[1][n];
}
}; class Solution {
public:
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
string LCS(string s1, string s2) {
// 时间复杂度O(MN),空间复杂度O(MN)
vector<vector<int>> dp(s1.size() + 1, vector<int>(s2.size() + 1, 0));
vector<vector<int>> path(s1.size() + 1, vector<int>(s2.size() + 1, 0));
for (int i = 1; i <= s1.size(); ++i) {
for (int j = 1; j <= s2.size(); ++j) {
if (s1[i - 1] == s2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
path[i][j] = 1;
} else if (dp[i - 1][j] > dp[i][j - 1]) {
dp[i][j] = dp[i - 1][j];
path[i][j] = 2;
} else {
dp[i][j] = dp[i][j - 1];
path[i][j] = 3;
}
}
}
string res = getStr(s1, s2, s1.size(), s2.size(), path);
return res.empty() ? "-1" : res;
}
string getStr(string &s1, string &s2, int i, int j, vector<vector<int>> &path) {
string res;
if (i == 0 || j == 0) return res;
if (path[i][j] == 1) {
res += getStr(s1, s2, i - 1, j - 1, path);
res += s1[i - 1];
} else if (path[i][j] == 2) {
res += getStr(s1, s2, i - 1, j, path);
} else if (path[i][j] == 3) {
res += getStr(s1, s2, i, j - 1, path);
}
return res;
}
}; import java.util.*;
public class Solution {
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
public String LCS (String s1, String s2) {
if (s1==null||s2==null||s1.length()==0||s2.length()==0){
return "-1";
}
int m=s1.length();
int n=s2.length();
//dp[a][b],a in [0,m], b in [0,n],定义为s1长度为a的前缀子串,s2长度为b的前缀子串,两个前缀子串的最大公共子序列
String[][]dp=new String[m+1][n+1];
for (int i=0;i<m+1; ++i){
dp[i][0] = "";
}
for (int j=0;j<n+1; ++j){
dp[0][j] = "";
}
for (int i=1; i<m+1; ++i){
for (int j=1; j<n+1; ++j){
if (s1.charAt(i-1) == s2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1] + s1.substring(i-1,i);
}else {
dp[i][j] = dp[i-1][j].length() > dp[i][j-1].length() ? dp[i-1][j] : dp[i][j-1];
}
}
}
String res = dp[m][n];
return res.isEmpty() ? "-1" : res;
}
} import java.util.*;
public class Solution {
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
public String LCS (String s1, String s2) {
// write code here
int len1 = s1.length();
int len2 = s2.length();
String[][] dp = new String[len1+1][len2+1];
//初始化
for(int i = 0;i <= len2;i++){
dp[0][i] = "";
}
for(int i = 0; i <= len1; i++){
dp[i][0] = "";
}
for(int i = 1; i <= len1; i++){
for(int j = 1;j <= len2; j++){
if(s1.charAt(i - 1) == s2.charAt( j - 1)){
dp[i][j] = dp[i-1][j-1] + s1.charAt(i-1);
}else{
dp[i][j] = dp[i-1][j].length() > dp[i][j-1].length()? dp[i-1][j]: dp[i][j-1];
}
}
}
return dp[len1][len2] == "" ? "-1" : dp[len1][len2];
}
}