两个字符串的最短可能组合

计算两个给定字符串组合的最短字符串,使新字符串由两个字符串组成,作为其 子序列 . 例如:

null
Input : a = "pear"        b = "peach"Output : pearchpearch is the shorted string such that bothpear and peach are its subsequences.Input  : a = "geek"         b = "code"Output : gecodek

我们在下面的文章中讨论了一种求最短超序列长度的方法。 最短公共超序列 在这篇文章中,讨论了超序列的打印。该解决方案基于下文中讨论的递归方法 以上职位 作为替代方法。

Let a[0..m-1] and b[0..n-1] be two strings and m andbe respective lengths.  if (m == 0) return n;  if (n == 0) return m;  // If last characters are same, then add 1 to  // result and recur for a[]  if (a[m-1] == b[n-1])      return 1 + SCS(a, b, m-1, n-1);  // Else find shortest of following two  //  a) Remove last character from X and recur  //  b) Remove last character from Y and recur  else return 1 + min( SCS(a, b, m-1, n),                        SCS(a, b, m, n-1) );

我们构建一个DP阵列来存储长度。在构建DP阵列后,我们从右下角的最位置开始遍历。印刷的方法类似于 打印LCS .

C++

/* C++ program to print supersequence of two
strings */
#include<bits/stdc++.h>
using namespace std;
/* Prints super sequence of a[0..m-1] and b[0..n-1] */
void printSuperSeq(string &a, string &b)
{
int m = a.length(), n = b.length();
int dp[m+1][n+1];
// Fill table in bottom up manner
for ( int i = 0; i <= m; i++)
{
for ( int j = 0; j <= n; j++)
{
// Below steps follow above recurrence
if (!i)
dp[i][j] = j;
else if (!j)
dp[i][j] = i;
else if (a[i-1] == b[j-1])
dp[i][j] = 1 + dp[i-1][j-1];
else
dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1]);
}
}
// Following code is used to print supersequence
int index = dp[m][n];
// Create a string of size index+1 to store the result
string res(index+1, ' ' );
// Start from the right-most-bottom-most corner and
// one by one store characters in res[]
int i = m, j = n;
while (i > 0 && j > 0)
{
// If current character in a[] and b are same,
// then current character is part of LCS
if (a[i-1] == b[j-1])
{
// Put current character in result
res[index-1] = a[i-1];
// reduce values of i, j and indexs
i--; j--; index--;
}
// If not same, then find the smaller of two and
// go in the direction of smaller value
else if (dp[i-1][j] < dp[i][j-1])
{ res[index-1] = a[i-1];   i--;  index--; }
else
{ res[index-1] = b[j-1];  j--; index--; }
}
// Copy remaining characters of string 'a'
while (i > 0)
{
res[index-1] = a[i-1];   i--;  index--;
}
// Copy remaining characters of string 'b'
while (j > 0)
{
res[index-1] = b[j-1];  j--; index--;
}
// Print the result
cout << res;
}
/* Driver program to test above function */
int main()
{
string a = "algorithm" , b = "rhythm" ;
printSuperSeq(a, b);
return 0;
}


JAVA

// Java program to print supersequence of two
// strings
public class GFG_1 {
String a , b;
// Prints super sequence of a[0..m-1] and b[0..n-1]
static void printSuperSeq(String a, String b)
{
int m = a.length(), n = b.length();
int [][] dp = new int [m+ 1 ][n+ 1 ];
// Fill table in bottom up manner
for ( int i = 0 ; i <= m; i++)
{
for ( int j = 0 ; j <= n; j++)
{
// Below steps follow above recurrence
if (i == 0 )
dp[i][j] = j;
else if (j == 0 )
dp[i][j] = i;
else if (a.charAt(i- 1 ) == b.charAt(j- 1 ))
dp[i][j] = 1 + dp[i- 1 ][j- 1 ];
else
dp[i][j] = 1 + Math.min(dp[i- 1 ][j], dp[i][j- 1 ]);
}
}
// Create a string of size index+1 to store the result
String res = "" ;
// Start from the right-most-bottom-most corner and
// one by one store characters in res[]
int i = m, j = n;
while (i > 0 && j > 0 )
{
// If current character in a[] and b are same,
// then current character is part of LCS
if (a.charAt(i- 1 ) == b.charAt(j- 1 ))
{
// Put current character in result
res = a.charAt(i- 1 ) + res;
// reduce values of i, j and indexs
i--;
j--;
}
// If not same, then find the larger of two and
// go in the direction of larger value
else if (dp[i- 1 ][j] < dp[i][j- 1 ])
{
res = a.charAt(i- 1 ) + res;
i--;
}
else
{
res = b.charAt(j- 1 ) + res;
j--;
}
}
// Copy remaining characters of string 'a'
while (i > 0 )
{
res = a.charAt(i- 1 ) + res;
i--;
}
// Copy remaining characters of string 'b'
while (j > 0 )
{
res = b.charAt(j- 1 ) + res;
j--;
}
// Print the result
System.out.println(res);
}
/* Driver program to test above function */
public static void main(String args[])
{
String a = "algorithm" ;
String b = "rhythm" ;
printSuperSeq(a, b);
}
}
// This article is contributed by Sumit Ghosh


Python3

# Python3 program to print supersequence of two strings
# Prints super sequence of a[0..m-1] and b[0..n-1]
def printSuperSeq(a, b):
m = len (a)
n = len (b)
dp = [[ 0 ] * (n + 1 ) for i in range (m + 1 )]
# Fill table in bottom up manner
for i in range ( 0 , m + 1 ):
for j in range ( 0 , n + 1 ):
# Below steps follow above recurrence
if not i:
dp[i][j] = j;
elif not j:
dp[i][j] = i;
elif (a[i - 1 ] = = b[j - 1 ]):
dp[i][j] = 1 + dp[i - 1 ][j - 1 ];
else :
dp[i][j] = 1 + min (dp[i - 1 ][j],
dp[i][j - 1 ]);
# Following code is used to print supersequence
index = dp[m][n];
# Create a string of size index+1
# to store the result
res = [""] * (index)
# Start from the right-most-bottom-most corner
# and one by one store characters in res[]
i = m
j = n;
while (i > 0 and j > 0 ):
# If current character in a[] and b are same,
# then current character is part of LCS
if (a[i - 1 ] = = b[j - 1 ]):
# Put current character in result
res[index - 1 ] = a[i - 1 ];
# reduce values of i, j and indexs
i - = 1
j - = 1
index - = 1
# If not same, then find the larger of two and
# go in the direction of larger value
elif (dp[i - 1 ][j] < dp[i][j - 1 ]):
res[index - 1 ] = a[i - 1 ]
i - = 1
index - = 1
else :
res[index - 1 ] = b[j - 1 ]
j - = 1
index - = 1
# Copy remaining characters of string 'a'
while (i > 0 ):
res[index - 1 ] = a[i - 1 ]
i - = 1
index - = 1
# Copy remaining characters of string 'b'
while (j > 0 ):
res[index - 1 ] = b[j - 1 ]
j - = 1
index - = 1
# Print the result
print ("".join(res))
# Driver Code
if __name__ = = '__main__' :
a = "algorithm"
b = "rhythm"
printSuperSeq(a, b)
# This code is contributed by ashutosh450


C#

// C# program to print supersequence of two
// strings
using System;
public class GFG_1 {
// Prints super sequence of a[0..m-1] and b[0..n-1]
static void printSuperSeq( string a, string b)
{
int m = a.Length, n = b.Length;
int [,] dp = new int [m+1,n+1];
// Fill table in bottom up manner
for ( int i = 0; i <= m; i++)
{
for ( int j = 0; j <= n; j++)
{
// Below steps follow above recurrence
if (i == 0)
dp[i,j] = j;
else if (j == 0 )
dp[i,j] = i;
else if (a[i-1] == b[j-1])
dp[i,j] = 1 + dp[i-1,j-1];
else
dp[i,j] = 1 + Math.Min(dp[i-1,j], dp[i,j-1]);
}
}
// Create a string of size index+1 to store the result
string res = "" ;
// Start from the right-most-bottom-most corner and
// one by one store characters in res[]
int k = m, l = n;
while (k > 0 && l > 0)
{
// If current character in a[] and b are same,
// then current character is part of LCS
if (a[k-1] == b[l-1])
{
// Put current character in result
res = a[k-1] + res;
// reduce values of i, j and indexs
k--;
l--;
}
// If not same, then find the larger of two and
// go in the direction of larger value
else if (dp[k-1,l] < dp[k,l-1])
{
res = a[k-1] + res;
k--;
}
else
{
res = b[l-1] + res;
l--;
}
}
// Copy remaining characters of string 'a'
while (k > 0)
{
res = a[k-1] + res;
k--;
}
// Copy remaining characters of string 'b'
while (l > 0)
{
res = b[l-1] + res;
l--;
}
// Print the result
Console.WriteLine(res);
}
/* Driver program to test above function */
public static void Main()
{
string a = "algorithm" ;
string b = "rhythm" ;
printSuperSeq(a, b);
}
}
// This article is contributed by Ita_c.


Javascript

<script>
// Javascript program to print supersequence of two
// strings
// Prints super sequence of a[0..m-1] and b[0..n-1]
function printSuperSeq(a,b)
{
let m = a.length, n = b.length;
let dp = new Array(m+1);
for (let i=0;i<m+1;i++)
dp[i]= new Array(n+1);
// Fill table in bottom up manner
for (let i = 0; i <= m; i++)
{
for (let j = 0; j <= n; j++)
{
// Below steps follow above recurrence
if (i == 0)
dp[i][j] = j;
else if (j == 0 )
dp[i][j] = i;
else if (a[i-1] == b[j-1])
dp[i][j] = 1 + dp[i-1][j-1];
else
dp[i][j] = 1 + Math.min(dp[i-1][j], dp[i][j-1]);
}
}
// Create a string of size index+1 to store the result
let res = "" ;
// Start from the right-most-bottom-most corner and
// one by one store characters in res[]
let i = m, j = n;
while (i > 0 && j > 0)
{
// If current character in a[] and b are same,
// then current character is part of LCS
if (a[i-1] == b[j-1])
{
// Put current character in result
res = a[i-1] + res;
// reduce values of i, j and indexs
i--;
j--;
}
// If not same, then find the larger of two and
// go in the direction of larger value
else if (dp[i-1][j] < dp[i][j-1])
{
res = a[i-1] + res;
i--;
}
else
{
res = b[j-1] + res;
j--;
}
}
// Copy remaining characters of string 'a'
while (i > 0)
{
res = a[i-1] + res;
i--;
}
// Copy remaining characters of string 'b'
while (j > 0)
{
res = b[j-1] + res;
j--;
}
// Print the result
document.write(res);
}
/* Driver program to test above function */
let a = "algorithm" ;
let b = "rhythm" ;
printSuperSeq(a, b);
// This code is contributed by ab2127
</script>


输出:

algorihythm

基于LCS的解决方案: 我们使用LCS解决方案构建2D阵列。如果两个指针位置的字符相等,我们将长度增加1,否则存储相邻位置的最大值。最后,我们回溯矩阵以找到索引向量遍历,从而产生尽可能短的组合。

C++

// C++ implementation to find shortest string for
// a combination of two strings
#include <bits/stdc++.h>
using namespace std;
// Vector that store the index of string a and b
vector< int > index_a;
vector< int > index_b;
// Subroutine to Backtrack the dp matrix to
// find the index vector traversing which would
// yield the shortest possible combination
void index( int dp[][100], string a, string b,
int size_a, int size_b)
{
// Clear the index vectors
index_a.clear();
index_b.clear();
// Return if either of a or b is reduced
// to 0
if (size_a == 0 || size_b == 0)
return ;
// Push both to index_a and index_b with
// the respective a and b index
if (a[size_a - 1] == b[size_b - 1]) {
index(dp, a, b, size_a - 1, size_b - 1);
index_a.push_back(size_a - 1);
index_b.push_back(size_b - 1);
} else {
if (dp[size_a - 1][size_b] > dp[size_a]
[size_b - 1]) {
index(dp, a, b, size_a - 1, size_b);
} else {
index(dp, a, b, size_a, size_b - 1);
}
}
}
// function to combine the strings to form
// the shortest string
void combine(string a, string b, int size_a,
int size_b)
{
int dp[100][100];
string ans = "" ;
int k = 0;
// Initialize the matrix to 0
memset (dp, 0, sizeof (dp));
// Store the increment of diagonally
// previous value if a[i-1] and b[j-1] are
// equal, else store the max of dp[i][j-1]
// and dp[i-1][j]
for ( int i = 1; i <= size_a; i++) {
for ( int j = 1; j <= size_b; j++) {
if (a[i - 1] == b[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i][j - 1],
dp[i - 1][j]);
}
}
}
// Get the Lowest Common Subsequence
int lcs = dp[size_a][size_b];
// Backtrack the dp array to get the index
// vectors of two strings, used to find
// the shortest possible combination.
index(dp, a, b, size_a, size_b);
int i, j = i = k;
// Build the string combination using the
// index found by backtracking
while (k < lcs) {
while (i < size_a && i < index_a[k]) {
ans += a[i++];
}
while (j < size_b && j < index_b[k]) {
ans += b[j++];
}
ans = ans + a[index_a[k]];
k++;
i++;
j++;
}
// Append the remaining characters in a
// to answer
while (i < size_a) {
ans += a[i++];
}
// Append the remaining characters in b
// to answer
while (j < size_b) {
ans += b[j++];
}
cout << ans;
}
// Driver code
int main()
{
string a = "algorithm" ;
string b = "rhythm" ;
// Store the length of string
int size_a = a.size();
int size_b = b.size();
combine(a, b, size_a, size_b);
return 0;
}


JAVA

// Java implementation to find shortest string for
// a combination of two strings
import java.util.ArrayList;
public class GFG_2 {
// Vector that store the index of string a and b
static ArrayList<Integer> index_a = new ArrayList<>();
static ArrayList<Integer> index_b = new ArrayList<>();
// Subroutine to Backtrack the dp matrix to
// find the index vector traversing which would
// yield the shortest possible combination
static void index( int dp[][], String a, String b,
int size_a, int size_b)
{
// Clear the index vectors
index_a.clear();
index_b.clear();
// Return if either of a or b is reduced
// to 0
if (size_a == 0 || size_b == 0 )
return ;
// Push both to index_a and index_b with
// the respective a and b index
if (a.charAt(size_a - 1 ) == b.charAt(size_b - 1 )) {
index(dp, a, b, size_a - 1 , size_b - 1 );
index_a.add(size_a - 1 );
index_b.add(size_b - 1 );
} else {
if (dp[size_a - 1 ][size_b] > dp[size_a]
[size_b - 1 ]) {
index(dp, a, b, size_a - 1 , size_b);
} else {
index(dp, a, b, size_a, size_b - 1 );
}
}
}
// function to combine the strings to form
// the shortest string
static void combine(String a, String b, int size_a,
int size_b)
{
int [][] dp = new int [ 100 ][ 100 ];
String ans = "" ;
int k = 0 ;
// Store the increment of diagonally
// previous value if a[i-1] and b[j-1] are
// equal, else store the max of dp[i][j-1]
// and dp[i-1][j]
for ( int i = 1 ; i <= size_a; i++) {
for ( int j = 1 ; j <= size_b; j++) {
if (a.charAt(i - 1 ) == b.charAt(j - 1 )) {
dp[i][j] = dp[i - 1 ][j - 1 ] + 1 ;
} else {
dp[i][j] = Math.max(dp[i][j - 1 ],
dp[i - 1 ][j]);
}
}
}
// Get the Lowest Common Subsequence
int lcs = dp[size_a][size_b];
// Backtrack the dp array to get the index
// vectors of two strings, used to find
// the shortest possible combination.
index(dp, a, b, size_a, size_b);
int i, j = i = k;
// Build the string combination using the
// index found by backtracking
while (k < lcs) {
while (i < size_a && i < index_a.get(k)) {
ans += a.charAt(i++);
}
while (j < size_b && j < index_b.get(k)) {
ans += b.charAt(j++);
}
ans = ans + a.charAt(index_a.get(k));
k++;
i++;
j++;
}
// Append the remaining characters in a
// to answer
while (i < size_a) {
ans += a.charAt(i++);
}
// Append the remaining characters in b
// to answer
while (j < size_b) {
ans +=  b.charAt(j++);
}
System.out.println(ans);
}
/* Driver program to test above function */
public static void main(String args[])
{
String a = "algorithm" ;
String b = "rhythm" ;
combine(a, b, a.length(),b.length());
}
}
// This article is contributed by Sumit Ghosh


Python3

# Python implementation to find shortest string for
# a combination of two strings
index_a = []
index_b = []
def index(dp, a, b, size_a, size_b):
if (size_a = = 0 or size_b = = 0 ):
return
if (a[size_a - 1 ] = = b[size_b - 1 ]):
index(dp, a, b, size_a - 1 , size_b - 1 )
index_a.append(size_a - 1 )
index_b.append(size_b - 1 )
else :
if (dp[size_a - 1 ][size_b] > dp[size_a][size_b - 1 ]):
index(dp, a, b, size_a - 1 , size_b)
else :
index(dp, a, b, size_a, size_b - 1 )
def combine(a, b, size_a, size_b):
dp = [[ 0 for i in range ( 100 )] for j in range ( 100 )]
ans = ""
k = 0
for i in range ( 1 , size_a + 1 ):
for j in range ( 1 , size_b + 1 ):
if (a[i - 1 ] = = b[j - 1 ]):
dp[i][j] = dp[i - 1 ][j - 1 ] + 1
else :
dp[i][j] = max (dp[i][j - 1 ], dp[i - 1 ][j])
lcs = dp[size_a][size_b]
index(dp, a, b, size_a, size_b)
j = i = k
while (k < lcs):
while (i < size_a and i < index_a[k]):
ans + = a[i];
i + = 1
while (j < size_b and j < index_b[k]):
ans + = b[j]
j + = 1
ans = ans + a[index_a[k]]
k + = 1
i + = 1
j + = 1
while (i < size_a):
ans + = a[i]
i + = 1
while (j < size_b):
ans + = b[j]
j + = 1
print (ans)
# Driver code
a = "algorithm"
b = "rhythm"
size_a = len (a)
size_b = len (b)
combine(a, b, size_a, size_b)
# This code is contributed by avanitrachhadiya2155


C#

// C# implementation to find shortest string for
// a combination of two strings
using System;
using System.Collections.Generic;
class GFG
{
// Vector that store the index of string a and b
static List< int > index_a = new List< int >();
static List< int > index_b = new List< int >();
// Subroutine to Backtrack the dp matrix to
// find the index vector traversing which would
// yield the shortest possible combination
static void index( int [,]dp, String a, String b,
int size_a, int size_b)
{
// Clear the index vectors
index_a.Clear();
index_b.Clear();
// Return if either of a or b is reduced
// to 0
if (size_a == 0 || size_b == 0)
return ;
// Push both to index_a and index_b with
// the respective a and b index
if (a[size_a - 1] == b[size_b - 1])
{
index(dp, a, b, size_a - 1, size_b - 1);
index_a.Add(size_a - 1);
index_b.Add(size_b - 1);
}
else
{
if (dp[size_a - 1,size_b] > dp[size_a,
size_b - 1])
{
index(dp, a, b, size_a - 1, size_b);
}
else
{
index(dp, a, b, size_a, size_b - 1);
}
}
}
// function to combine the strings to form
// the shortest string
static void combine(String a, String b,
int size_a, int size_b)
{
int [,] dp = new int [100, 100];
String ans = "" ;
int k = 0, i, j;
// Store the increment of diagonally
// previous value if a[i-1] and b[j-1] are
// equal, else store the max of dp[i,j-1]
// and dp[i-1,j]
for (i = 1; i <= size_a; i++)
{
for (j = 1; j <= size_b; j++)
{
if (a[i-1] == b[j - 1])
{
dp[i, j] = dp[i - 1, j - 1] + 1;
}
else
{
dp[i, j] = Math.Max(dp[i, j - 1],
dp[i - 1, j]);
}
}
}
// Get the Lowest Common Subsequence
int lcs = dp[size_a, size_b];
// Backtrack the dp array to get the index
// vectors of two strings, used to find
// the shortest possible combination.
index(dp, a, b, size_a, size_b);
i = j = k;
// Build the string combination using the
// index found by backtracking
while (k < lcs)
{
while (i < size_a && i < index_a[k])
{
ans += a[i++];
}
while (j < size_b && j < index_b[k])
{
ans += b[j++];
}
ans = ans + a[index_a[k]];
k++;
i++;
j++;
}
// Append the remaining characters in a
// to answer
while (i < size_a)
{
ans += a[i++];
}
// Append the remaining characters in b
// to answer
while (j < size_b)
{
ans += b[j++];
}
Console.WriteLine(ans);
}
// Driver Code
public static void Main(String []args)
{
String a = "algorithm" ;
String b = "rhythm" ;
combine(a, b, a.Length,b.Length);
}
}
// This code is contributed by Princi Singh


Javascript

<script>
// JavaScript implementation to find shortest string for
// a combination of two strings
// Vector that store the index of string a and b
let index_a =[];
let index_b = [];
// Subroutine to Backtrack the dp matrix to
// find the index vector traversing which would
// yield the shortest possible combination
function index(dp,a,b,size_a,size_b)
{
// Clear the index vectors
index_a=[];
index_b=[];
// Return if either of a or b is reduced
// to 0
if (size_a == 0 || size_b == 0)
return ;
// Push both to index_a and index_b with
// the respective a and b index
if (a[size_a - 1] == b[size_b - 1]) {
index(dp, a, b, size_a - 1, size_b - 1);
index_a.push(size_a - 1);
index_b.push(size_b - 1);
} else {
if (dp[size_a - 1][size_b] > dp[size_a]
[size_b - 1]) {
index(dp, a, b, size_a - 1, size_b);
} else {
index(dp, a, b, size_a, size_b - 1);
}
}
}
// function to combine the strings to form
// the shortest string
function combine(a,b,size_a,size_b)
{
let dp = new Array(100);
for (let i=0;i<100;i++)
{
dp[i]= new Array(100);
for (let j=0;j<100;j++)
{
dp[i][j]=0;
}
}
let ans = "" ;
let k = 0;
// Store the increment of diagonally
// previous value if a[i-1] and b[j-1] are
// equal, else store the max of dp[i][j-1]
// and dp[i-1][j]
for (let i = 1; i <= size_a; i++) {
for (let j = 1; j <= size_b; j++) {
if (a[i - 1] == b[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i][j - 1],
dp[i - 1][j]);
}
}
}
// Get the Lowest Common Subsequence
let lcs = dp[size_a][size_b];
// Backtrack the dp array to get the index
// vectors of two strings, used to find
// the shortest possible combination.
index(dp, a, b, size_a, size_b);
let i, j = i = k;
// Build the string combination using the
// index found by backtracking
while (k < lcs) {
while (i < size_a && i < index_a[k]) {
ans += a[i++];
}
while (j < size_b && j < index_b[k]) {
ans += b[j++];
}
ans = ans + a[index_a[k]];
k++;
i++;
j++;
}
// Append the remaining characters in a
// to answer
while (i < size_a) {
ans += a[i++];
}
// Append the remaining characters in b
// to answer
while (j < size_b) {
ans +=  b[j++];
}
document.write(ans+ "<br>" );
}
/* Driver program to test above function */
let a = "algorithm" ;
let b = "rhythm" ;
combine(a, b, a.length,b.length);
// This code is contributed by patel2127
</script>


输出:

algorihythm

本文由 拉加夫·贾乔迪亚 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄去评论-team@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享