Shortest Uncommon Subsequence
Last Updated :
27 Jan, 2023
Given two strings S and T, find the length of the shortest subsequence in S which is not a subsequence in T. If no such subsequence is possible, return -1. A subsequence is a sequence that appears in the same relative order, but is not necessarily contiguous. A string of length n has 2^n different possible subsequences.
String S of length m (1 <= m <= 1000)
String T of length n (1 <= n <= 1000)
Examples:
Input : S = “babab” T = “babba”
Output : 3
Explanation: The subsequence “aab” of length 3 is present in S but not in T.
Input : S = “abb” T = “abab”
Output : -1
Explanation: There is no subsequence that is present in S but not in T.
Brute Force Method
A simple approach will be to generate all the subsequences of string S and for each subsequence check if it is present in string T or not. Consider example 2 in which S = “abb”,
its subsequences are “”, ”a”, ”b”, ”ab”, ”bb”, ”abb” each of which is present in “abab”. The time complexity of this solution will be exponential.
Efficient (Dynamic Programming):
1. Optimal substructure: Consider two strings S and T of length m and n respectively & let the function to find the shortest uncommon subsequence be shortestSeq (char *S, char *T). For each character in S, if it is not present in T then that character is the answer itself.
Otherwise, if it is found at index k then we have the choice of either including it in the shortest uncommon subsequence or not.
If it is included answer = 1 + ShortestSeq( S + 1, T + k + 1)
If not included answer = ShortestSeq( S + 1, T)
The minimum of the two is the answer.
Thus, we can see that this problem has optimal substructure properties as it can be solved by using solutions to subproblems.
2. Overlapping Subproblems: Following is a simple recursive implementation of the above problem.
C++
#include<bits/stdc++.h>
using namespace std;
#define MAX 1005
int shortestSeq( char *S, char *T, int m, int n)
{
if (m == 0)
return MAX;
if (n <= 0)
return 1;
int k;
for (k=0; k < n; k++)
if (T[k] == S[0])
break ;
if (k == n)
return 1;
return min(shortestSeq(S+1, T, m-1, n),
1 + shortestSeq(S+1, T+k+1, m-1, n-k-1));
}
int main()
{
char S[] = "babab" ;
char T[] = "babba" ;
int m = strlen (S), n = strlen (T);
int ans = shortestSeq(S, T, m, n);
if (ans >= MAX)
ans = -1;
cout << "Length of shortest subsequence is: "
<< ans << endl;
return 0;
}
|
Java
import java.util.*;
class GFG
{
static final int MAX = 1005 ;
static int shortestSeq( char []S, char []T, int m, int n)
{
if (m == 0 )
return MAX;
if (n <= 0 )
return 1 ;
int k;
for (k = 0 ; k < n; k++)
if (T[k] == S[ 0 ])
break ;
if (k == n)
return 1 ;
return Math.min(shortestSeq(Arrays.copyOfRange(S, 1 , S.length), T, m - 1 , n),
1 + shortestSeq(Arrays.copyOfRange(S, 1 , S.length),
Arrays.copyOfRange(T, k + 1 , T.length), m - 1 , n - k - 1 ));
}
public static void main(String[] args)
{
char S[] = "babab" .toCharArray();
char T[] = "babba" .toCharArray();
int m = S.length, n = T.length;
int ans = shortestSeq(S, T, m, n);
if (ans >= MAX)
ans = - 1 ;
System.out.print( "Length of shortest subsequence is: "
+ ans + "\n" );
}
}
|
Python3
MAX = 1005
def shortestSeq(S, T, m, n):
if m = = 0 :
return MAX
if (n < = 0 ):
return 1
for k in range (n):
if (T[k] = = S[ 0 ]):
break
if (k = = n):
return 1
return min (shortestSeq(S[ 1 : ], T, m - 1 , n),
1 + shortestSeq((S[ 1 : ]), T[k + 1 : ],
m - 1 , n - k - 1 ))
S = "babab"
T = "babba"
m = len (S)
n = len (T)
ans = shortestSeq(S, T, m, n)
if (ans > = MAX ):
ans = - 1
print ( "Length of shortest subsequence is:" , ans)
|
C#
using System;
class GFG
{
static readonly int MAX = 1005;
static int shortestSeq( char []S, char []T, int m, int n)
{
if (m == 0)
return MAX;
if (n <= 0)
return 1;
int k;
for (k = 0; k < n; k++)
if (T[k] == S[0])
break ;
if (k == n)
return 1;
char []St1 = new Char[S.Length - 1];
Array.Copy(S, 1, St1, 0, S.Length - 1);
char []St2 = new Char[S.Length - 1];
Array.Copy(S, 1, St2, 0, S.Length - 1);
char []Tt1 = new Char[T.Length - (k + 1)];
Array.Copy(T, k + 1, Tt1, 0, T.Length - (k + 1));
return Math.Min(shortestSeq(St1, T, m - 1, n),
1 + shortestSeq(St2, Tt1, m - 1, n - k - 1));
}
public static void Main(String[] args)
{
char []S = "babab" .ToCharArray();
char []T = "babba" .ToCharArray();
int m = S.Length, n = T.Length;
int ans = shortestSeq(S, T, m, n);
if (ans >= MAX)
ans = -1;
Console.Write( "Length of shortest subsequence is: "
+ ans + "\n" );
}
}
|
Javascript
<script>
const MAX = 1005
function shortestSeq(S, T, m, n){
if (m == 0)
return MAX
if (n <= 0)
return 1
let k;
for (k=0;k<n;k++){
if (T[k] == S[0])
break
}
if (k == n)
return 1
return Math.min(shortestSeq(S.substring(1,), T, m - 1, n),
1 + shortestSeq((S.substring(1,)), T.substring(k + 1,),
m - 1, n - k - 1))
}
let S = "babab"
let T = "babba"
let m = S.length
let n = T.length
let ans = shortestSeq(S, T, m, n)
if (ans >= MAX)
ans =- 1
document.write( "Length of shortest subsequence is: " + ans, "</br>" )
</script>
|
Output
Length of shortest subsequence is: 3
Time complexity: O(m*n),The time complexity of this algorithm is O(m*n), where m and n are the lengths of the two strings. This is because the algorithm uses a recursive approach to find the shortest uncommon subsequence which involves comparing each character of the two strings.
Auxiliary Space: O(m*n),The space complexity of this algorithm is also O(m*n) because we are using a two-dimensional array to store the result of the recursive call.
If we draw the complete recursion tree, then we can see that there are many subproblems that are solved again and again. So this problem has Overlapping Substructure property and re-computation of the same subproblems can be avoided by either using Memoization or Tabulation. The following is a tabulated implementation of the problem.
C++
#include<bits/stdc++.h>
using namespace std;
#define MAX 1005
int shortestSeq( char *S, char *T)
{
int m = strlen (S), n = strlen (T);
int dp[m+1][n+1];
for ( int i = 0; i <= m; i++)
dp[i][0] = 1;
for ( int i = 0; i <= n; i++)
dp[0][i] = MAX;
for ( int i = 1; i <= m; i++)
{
for ( int j = 1; j <= n; j++)
{
char ch = S[i-1];
int k;
for (k = j-1; k >= 0; k--)
if (T[k] == ch)
break ;
if (k == -1)
dp[i][j] = 1;
else
dp[i][j] = min(dp[i-1][j], dp[i-1][k] + 1);
}
}
int ans = dp[m][n];
if (ans >= MAX)
ans = -1;
return ans;
}
int main()
{
char S[] = "babab" ;
char T[] = "babba" ;
int m = strlen (S), n = strlen (T);
cout << "Length of shortest subsequence is : "
<< shortestSeq(S, T) << endl;
}
|
Java
import java.io.*;
class GFG
{
static final int MAX = 1005 ;
static int shortestSeq( char [] S, char [] T)
{
int m = S.length, n = T.length;
int dp[][] = new int [m + 1 ][n + 1 ];
for ( int i = 0 ; i <= m; i++)
{
dp[i][ 0 ] = 1 ;
}
for ( int i = 0 ; i <= n; i++)
{
dp[ 0 ][i] = MAX;
}
for ( int i = 1 ; i <= m; i++)
{
for ( int j = 1 ; j <= n; j++)
{
char ch = S[i - 1 ];
int k;
for (k = j - 1 ; k >= 0 ; k--)
{
if (T[k] == ch)
{
break ;
}
}
if (k == - 1 )
{
dp[i][j] = 1 ;
}
else
{
dp[i][j] = Math.min(dp[i - 1 ][j],
dp[i - 1 ][k] + 1 );
}
}
}
int ans = dp[m][n];
if (ans >= MAX)
{
ans = - 1 ;
}
return ans;
}
public static void main(String[] args)
{
char S[] = "babab" .toCharArray();
char T[] = "babba" .toCharArray();
int m = S.length, n = T.length;
System.out.println( "Length of shortest" +
"subsequence is : " +
shortestSeq(S, T));
}
}
|
Python3
MAX = 1005
def shortestSeq(S: list , T: list ):
m = len (S)
n = len (T)
dp = [[ 0 for i in range (n + 1 )]
for j in range (m + 1 )]
for i in range (m + 1 ):
dp[i][ 0 ] = 1
for i in range (n + 1 ):
dp[ 0 ][i] = MAX
for i in range ( 1 , m + 1 ):
for j in range ( 1 , n + 1 ):
ch = S[i - 1 ]
k = j - 1
while k > = 0 :
if T[k] = = ch:
break
k - = 1
if k = = - 1 :
dp[i][j] = 1
else :
dp[i][j] = min (dp[i - 1 ][j],
dp[i - 1 ][k] + 1 )
ans = dp[m][n]
if ans > = MAX :
ans = - 1
return ans
if __name__ = = "__main__" :
S = "babab"
T = "babba"
print ( "Length of shortest subsequence is:" ,
shortestSeq(S, T))
|
C#
using System;
class GFG
{
static readonly int MAX = 1005;
static int shortestSeq( char [] S, char [] T)
{
int m = S.Length, n = T.Length;
int [,]dp = new int [m + 1, n + 1];
for ( int i = 0; i <= m; i++)
{
dp[i, 0] = 1;
}
for ( int i = 0; i <= n; i++)
{
dp[0, i] = MAX;
}
for ( int i = 1; i <= m; i++)
{
for ( int j = 1; j <= n; j++)
{
char ch = S[i - 1];
int k;
for (k = j - 1; k >= 0; k--)
{
if (T[k] == ch)
{
break ;
}
}
if (k == -1)
{
dp[i, j] = 1;
}
else
{
dp[i, j] = Math.Min(dp[i - 1, j],
dp[i - 1, k] + 1);
}
}
}
int ans = dp[m, n];
if (ans >= MAX)
{
ans = -1;
}
return ans;
}
public static void Main(String[] args)
{
char []S = "babab" .ToCharArray();
char []T = "babba" .ToCharArray();
int m = S.Length, n = T.Length;
Console.WriteLine( "Length of shortest" +
"subsequence is : " +
shortestSeq(S, T));
}
}
|
PHP
<?php
$GLOBALS [ 'MAX' ] = 1005;
function shortestSeq( $S , $T )
{
$m = strlen ( $S );
$n = strlen ( $T );
$dp = array ( array ());
for ( $i = 0; $i <= $m ; $i ++)
$dp [ $i ][0] = 1;
for ( $i = 0; $i <= $n ; $i ++)
$dp [0][ $i ] = $GLOBALS [ 'MAX' ];
for ( $i = 1; $i <= $m ; $i ++)
{
for ( $j = 1; $j <= $n ; $j ++)
{
$ch = $S [ $i - 1];
for ( $k = $j - 1; $k >= 0; $k --)
if ( $T [ $k ] == $ch )
break ;
if ( $k == -1)
$dp [ $i ][ $j ] = 1;
else
$dp [ $i ][ $j ] = min( $dp [ $i - 1][ $j ],
$dp [ $i - 1][ $k ] + 1);
}
}
$ans = $dp [ $m ][ $n ];
if ( $ans >= $GLOBALS [ 'MAX' ])
$ans = -1;
return $ans ;
}
$S = "babab" ;
$T = "babba" ;
$m = strlen ( $S );
$n = strlen ( $T );
echo "Length of shortest subsequence is : " ,
shortestSeq( $S , $T );
?>
|
Javascript
<script>
const MAX = 1005
function shortestSeq(S, T)
{
let m = S.length, n = T.length;
let dp = new Array(m+1).fill(0).map(()=> new Array(n+1).fill(0));
for (let i = 0; i <= m; i++)
dp[i][0] = 1;
for (let i = 0; i <= n; i++)
dp[0][i] = MAX;
for (let i = 1; i <= m; i++)
{
for (let j = 1; j <= n; j++)
{
let ch = S[i-1];
let k;
for (k = j-1; k >= 0; k--)
if (T[k] == ch)
break ;
if (k == -1)
dp[i][j] = 1;
else
dp[i][j] = Math.min(dp[i-1][j], dp[i-1][k] + 1);
}
}
let ans = dp[m][n];
if (ans >= MAX)
ans = -1;
return ans;
}
let S = "babab" ;
let T = "babba" ;
let m = S.length, n = T.length;
document.write( "Length of shortest subsequence is : " +shortestSeq(S, T), "</br>" );
</script>
|
Output
Length of shortest subsequence is : 3
Time Complexity: O(m*n)
Auxiliary Space: O(m*n)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...