Find length of smallest substring of a given string which contains another string as subsequence
Last Updated :
27 May, 2022
Given two strings A and B, the task is to find the smallest substring of A having B as a subsequence. If there are multiple such substrings in A, return the substring that has the smallest starting index.
Examples :
Input : A = "abcedbaced" B = "bed"
Output : "bced"
Explanation : The substring A[2 : 5] is the shortest substring that contains the string 'B' as a subsequence.
Input : A = "abcdbad" B = "bd"
Output : "bcd"
Explanation : Although both the substrings A[2:4] and A[5:7] have the same length, the substring which has the smallest starting index is "bcd" so it is the final answer.
Naive Approach: The simplest approach to solve the given problem is to check for string B occurring as a subsequence in every substring of A.
Among such substrings, the answer will be the one shortest in length and which has the smallest index.
Time Complexity: O(N3)
Auxiliary Space: O(1)
Efficient Approach: The above approach can also be optimized by using Dynamic Programming because the above problem has Overlapping subproblems and an Optimal substructure. The subproblems can be stored in dp[][] table memoization where dp[i][j] denotes that in the substring A(0...i) there exists a subsequence corresponding to B(0…j) which begins at index dp[i][j]. Follow the steps below to solve the problem:
- Initialize a global multidimensional array dp[100][100] with all values as -1 that stores the result of each dp state.
- Each column in the dp table represents a character in string B.
- Initialize the first column of the dp array, i.e., store the nearest occurrence of the first character of string B in every prefix of string A.
- Fill the remaining columns of the dp table. For a particular character in string B at position 'j', check if there exists a matching character in string A.
- If A[i] == B[j], then starting index of the required substring in the string A is equal to the starting index when the first j - 1 characters of string B are matched with the first i - 1 characters of string A.
- If A[i] != B[j], then starting index of the required substring in the string A is equal to the starting index when the first j characters of string B are matched with the first i - 1 characters of string A.
- Check if any of the values in the last column of dp table is greater than or equal to 0. For a particular index i in string A, if dp[i][b - 1] >= 0, then the required substring which has B as a subsequence is A[dp[i][b-1] : i]. Update the answer with the shortest possible substring.
Below is the implementation of the above approach:
C++
// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
// Stores the dp-states
int dp[100][100];
// Function to find the smallest substring in string A which
// contains string B as a subsequence.
string smallestSubstring(string& A, string& B)
{
// Size of string A
int a = A.size();
// Size of string B
int b = B.size();
// Initializing the first column of dp array.
// Storing the occurrence of first character of string B
// in first (i + 1) characters of string A.
for (int i = 0; i < a; ++i) {
// If the current character of string A does not
// match the first character of string B.
if (i > 0 and A[i] != B[0]) {
dp[i][0] = dp[i - 1][0];
}
// If the current character of string A is equal to
// the first character of string B.
if (A[i] == B[0]) {
dp[i][0] = i;
}
}
// Iterating through remaining characters of string B.
for (int j = 1; j < b; ++j) {
// Checking if any character in string A matches
// with the current character of string B.
for (int i = 1; i < a; ++i) {
// If there is a match, then starting index of
// required substring in string 'A' is equal to
// the starting index when first 'j - 1'
// characters of string 'B' matched with first
// 'i - 1' characters of string 'A'.
if (A[i] == B[j]) {
dp[i][j] = dp[i - 1][j - 1];
}
// Else, starting index of required substring in
// string 'A' is equal to the starting index
// when first 'j' characters of string 'B'
// matched with first 'i - 1' characters of
// string 'A'.
else {
dp[i][j] = dp[i - 1][j];
}
}
}
// String for storing final answer
string answer = "";
// Length of smallest substring
int best_length = 1e9;
for (int i = 0; i < a; ++i) {
// dp[i][b-1] is the index in string 'A', such that
// the substring A(dp[i][b-1] : i) contains string
// 'B' as a subsequence.
if (dp[i][b - 1] != -1) {
// Starting index of substring
int start = dp[i][b - 1];
// Ending index of substring
int end = i;
// Length of substring
int current_length = end - start + 1;
// if current length is lesser than the best
// length update the answer.
if (current_length < best_length) {
best_length = current_length;
// Update the answer
answer = A.substr(start, best_length);
}
}
}
// Return the smallest substring
return answer;
}
// This function is initializing dp with -1
// and printing the result
void smallestSubstringUtil(string& A, string& B)
{
// Initialize dp array with -1
memset(dp, -1, sizeof dp);
// Function call
cout << smallestSubstring(A, B) << endl;
}
// Driver code
int main()
{
// Input strings
string A = "abcedbaced";
string B = "bed";
// Function Call
smallestSubstringUtil(A, B);
return 0;
}
Java
// Java implementation of above approach
import java.io.*;
import java.util.*;
class GFG {
// Stores the dp-states
static int[][] dp = new int[100][100];
// Function to find the smallest subString in String A which
// contains String B as a subsequence.
static String smallestSubstring(String A, String B)
{
// Size of String A
int a = A.length();
// Size of String B
int b = B.length();
// Initializing the first column of dp array.
// Storing the occurrence of first character of String B
// in first (i + 1) characters of String A.
for (int i = 0; i < a; ++i) {
// If the current character of String A does not
// match the first character of String B.
if (i > 0 && A.charAt(i) != B.charAt(0)) {
dp[i][0] = dp[i - 1][0];
}
// If the current character of String A is equal to
// the first character of String B.
if (A.charAt(i) == B.charAt(0)) {
dp[i][0] = i;
}
}
// Iterating through remaining characters of String B.
for (int j = 1; j < b; ++j) {
// Checking if any character in String A matches
// with the current character of String B.
for (int i = 1; i < a; ++i) {
// If there is a match, then starting index of
// required subString in String 'A' is equal to
// the starting index when first 'j - 1'
// characters of String 'B' matched with first
// 'i - 1' characters of String 'A'.
if (A.charAt(i) == B.charAt(j)) {
dp[i][j] = dp[i - 1][j - 1];
}
// Else, starting index of required subString in
// String 'A' is equal to the starting index
// when first 'j' characters of String 'B'
// matched with first 'i - 1' characters of
// String 'A'.
else {
dp[i][j] = dp[i - 1][j];
}
}
}
// String for storing final answer
String answer = "";
// Length of smallest substring
int best_length = 100000000;
for (int i = 0; i < a; ++i) {
// dp[i][b-1] is the index in String 'A', such that
// the subString A(dp[i][b-1] : i) contains string
// 'B' as a subsequence.
if (dp[i][b - 1] != -1) {
// Starting index of substring
int start = dp[i][b - 1];
// Ending index of substring
int end = i;
// Length of substring
int current_length = end - start + 1;
// if current length is lesser than the best
// length update the answer.
if (current_length < best_length) {
best_length = current_length;
// Update the answer
answer = A.substring(start, best_length+1);
}
}
}
// Return the smallest substring
return answer;
}
// This function is initializing dp with -1
// and printing the result
static void smallestSubstringUtil(String A, String B)
{
// Initialize dp array with -1
for(int i=0;i<100;i++)
{
for(int j=0;j<100;j++)
{
dp[i][j] = -1;
}
}
// Function call
System.out.print( smallestSubstring(A, B) );
}
// Driver Code
public static void main(String[] args)
{
// Input strings
String A = "abcedbaced";
String B = "bed";
// Function Call
smallestSubstringUtil(A, B);
}
}
// This code is contributed by sanjoy_62.
Python3
# python3 program for the above approach
# Stores the dp-states
dp = [[-1 for _ in range(100)] for _ in range(100)]
# Function to find the smallest substring in string A which
# contains string B as a subsequence.
def smallestSubstring(A, B):
# Size of string A
a = len(A)
# Size of string B
b = len(B)
# Initializing the first column of dp array.
# Storing the occurrence of first character of string B
# in first (i + 1) characters of string A.
for i in range(0, a):
# If the current character of string A does not
# match the first character of string B.
if (i > 0 and A[i] != B[0]):
dp[i][0] = dp[i - 1][0]
# If the current character of string A is equal to
# the first character of string B.
if (A[i] == B[0]):
dp[i][0] = i
# Iterating through remaining characters of string B.
for j in range(1, b):
# Checking if any character in string A matches
# with the current character of string B.
for i in range(1, a):
# If there is a match, then starting index of
# required substring in string 'A' is equal to
# the starting index when first 'j - 1'
# characters of string 'B' matched with first
# 'i - 1' characters of string 'A'.
if (A[i] == B[j]):
dp[i][j] = dp[i - 1][j - 1]
# Else, starting index of required substring in
# string 'A' is equal to the starting index
# when first 'j' characters of string 'B'
# matched with first 'i - 1' characters of
# string 'A'.
else:
dp[i][j] = dp[i - 1][j]
# String for storing final answer
answer = ""
# Length of smallest substring
best_length = 1e9
for i in range(0, a):
# dp[i][b-1] is the index in string 'A', such that
# the substring A(dp[i][b-1] : i) contains string
# 'B' as a subsequence.
if (dp[i][b - 1] != -1):
# Starting index of substring
start = dp[i][b - 1]
# Ending index of substring
end = i
# Length of substring
current_length = end - start + 1
# if current length is lesser than the best
# length update the answer.
if (current_length < best_length):
best_length = current_length
# Update the answer
answer = A[start: start + best_length]
# Return the smallest substring
return answer
# This function is initializing dp with -1
# and printing the result
def smallestSubstringUtil(A, B):
# Initialize dp array with -1
# Function call
print(smallestSubstring(A, B))
# Driver code
if __name__ == "__main__":
# Input strings
A = "abcedbaced"
B = "bed"
# Function Call
smallestSubstringUtil(A, B)
# This code is contributed by rakeshsahni
C#
// C# program of the above approach
using System;
using System.Linq;
using System.Collections.Generic;
class GFG
{
// Stores the dp-states
static int[,] dp = new int[100, 100];
// Function to find the smallest substring in string A which
// contains string B as a subsequence.
static string smallestSubstring(string A, string B)
{
// Size of string A
int a = A.Length;
// Size of string B
int b = B.Length;
// Initializing the first column of dp array.
// Storing the occurrence of first character of string B
// in first (i + 1) characters of string A.
for (int i = 0; i < a; ++i) {
// If the current character of string A does not
// match the first character of string B.
if (i > 0 && A[i] != B[0]) {
dp[i,0] = dp[i - 1, 0];
}
// If the current character of string A is equal to
// the first character of string B.
if (A[i] == B[0]) {
dp[i,0] = i;
}
}
// Iterating through remaining characters of string B.
for (int j = 1; j < b; ++j) {
// Checking if any character in string A matches
// with the current character of string B.
for (int i = 1; i < a; ++i) {
// If there is a match, then starting index of
// required substring in string 'A' is equal to
// the starting index when first 'j - 1'
// characters of string 'B' matched with first
// 'i - 1' characters of string 'A'.
if (A[i] == B[j]) {
dp[i,j] = dp[i - 1,j - 1];
}
// Else, starting index of required substring in
// string 'A' is equal to the starting index
// when first 'j' characters of string 'B'
// matched with first 'i - 1' characters of
// string 'A'.
else {
dp[i,j] = dp[i - 1,j];
}
}
}
// String for storing final answer
string answer = "";
// Length of smallest substring
int best_length = 100000000;
for (int i = 0; i < a; ++i) {
// dp[i][b-1] is the index in string 'A', such that
// the substring A(dp[i][b-1] : i) contains string
// 'B' as a subsequence.
if (dp[i,b - 1] != -1) {
// Starting index of substring
int start = dp[i,b - 1];
// Ending index of substring
int end = i;
// Length of substring
int current_length = end - start + 1;
// if current length is lesser than the best
// length update the answer.
if (current_length < best_length) {
best_length = current_length;
// Update the answer
answer = A.Substring(start, best_length);
}
}
}
// Return the smallest substring
return answer;
}
// This function is initializing dp with -1
// and printing the result
static void smallestSubstringUtil(string A, string B)
{
// Initialize dp array with -1
for(int i=0;i<100;i++)
{
for(int j=0;j<100;j++)
{
dp[i,j] = -1;
}
}
// Function call
Console.Write( smallestSubstring(A, B));
}
// Driver Code
public static void Main()
{
// Input strings
string A = "abcedbaced";
string B = "bed";
// Function Call
smallestSubstringUtil(A, B);
}
}
// This code is contributed by sanjoy_62.
JavaScript
<script>
// JavaScript code for the above approach
// Stores the dp-states
let dp = new Array(100);
for (let i = 0; i < dp.length; i++) {
dp[i] = new Array(100).fill(-1)
}
// Function to find the smallest substring in string A which
// contains string B as a subsequence.
function smallestSubstring(A, B) {
// Size of string A
let a = A.length;
// Size of string B
let b = B.length;
// Initializing the first column of dp array.
// Storing the occurrence of first character of string B
// in first (i + 1) characters of string A.
for (let i = 0; i < a; ++i) {
// If the current character of string A does not
// match the first character of string B.
if (i > 0 && A[i] != B[0]) {
dp[i][0] = dp[i - 1][0];
}
// If the current character of string A is equal to
// the first character of string B.
if (A[i] == B[0]) {
dp[i][0] = i;
}
}
// Iterating through remaining characters of string B.
for (let j = 1; j < b; ++j) {
// Checking if any character in string A matches
// with the current character of string B.
for (let i = 1; i < a; ++i) {
// If there is a match, then starting index of
// required substring in string 'A' is equal to
// the starting index when first 'j - 1'
// characters of string 'B' matched with first
// 'i - 1' characters of string 'A'.
if (A[i] == B[j]) {
dp[i][j] = dp[i - 1][j - 1];
}
// Else, starting index of required substring in
// string 'A' is equal to the starting index
// when first 'j' characters of string 'B'
// matched with first 'i - 1' characters of
// string 'A'.
else {
dp[i][j] = dp[i - 1][j];
}
}
}
// String for storing final answer
let answer = "";
// Length of smallest substring
let best_length = 1e9;
for (let i = 0; i < a; ++i) {
// dp[i][b-1] is the index in string 'A', such that
// the substring A(dp[i][b-1] : i) contains string
// 'B' as a subsequence.
if (dp[i][b - 1] != -1) {
// Starting index of substring
let start = dp[i][b - 1];
// Ending index of substring
let end = i;
// Length of substring
let current_length = end - start + 1;
// if current length is lesser than the best
// length update the answer.
if (current_length < best_length) {
best_length = current_length;
// Update the answer
answer = A.slice(start, start + best_length);
}
}
}
// Return the smallest substring
return answer;
}
// This function is initializing dp with -1
// and printing the result
function smallestSubstringUtil(A, B) {
// Function call
document.write(smallestSubstring(A, B) + "<br>");
}
// Driver code
// Input strings
let A = "abcedbaced";
let B = "bed";
// Function Call
smallestSubstringUtil(A, B);
// This code is contributed by Potta Lokesh
</script>
Time Complexity: O(N2)
Auxiliary Space: O(N2)
Similar Reads
Find length of longest subsequence of one string which is substring of another string
Given two strings X and Y. The task is to find the length of the longest subsequence of string X which is a substring in sequence Y.Examples: Input : X = "ABCD", Y = "BACDBDCD"Output : 3Explanation: "ACD" is longest subsequence of X which is substring of Y.Input : X = "A", Y = "A"Output : 1Perquisit
15+ min read
Count of substrings of a string containing another given string as a substring | Set 2
Given two strings S and T of length N and M respectively, the task is to count the number of substrings of S that contains the string T in it as a substring. Examples: Input: S = âdabcâ, T = âabâOutput: 4Explanation:Substrings of S containing T as a substring are: S[0, 2] = âdabâS[1, 2] = âabâS[1, 3
8 min read
Find the longest subsequence of a string that is a substring of another string
Given two strings X and Y consisting of N and M characters, the task is to find the longest subsequence of a string X which is a substring of the string Y. Examples: Input: X = "ABCD", Y = "ACDBDCD"Output: ACDExplanation:"ACD" is longest subsequence of X which is substring of Y. Input: X = A, Y = AO
10 min read
Count of substrings of a string containing another given string as a substring
Given two strings S and T, the task is to count the number of substrings of S that contains string T in it as a substring. Examples: Input: S = "dabc", T = "ab"Output: 4Explanation: Substrings of S containing T as a substring are: S[0, 2] = âdabâS[1, 2] = âabâS[1, 3] = âabcâS[0, 3] = âdabcâ Input: S
8 min read
Smallest String consisting of a String S exactly K times as a Substring
Given a string S of length N and integer K, find the smallest length string which contains the string S as a sub string exactly K times. Examples: Input: S = "abba", K = 3 Output: abbabbabba Explanation: The string "abba" occurs K times in the string abbabbabba, i.e. {abbabbabba, abbabbabba, abbabba
6 min read
Lexicographically smallest string which is not a subsequence of given string
Given a string S, the task is to find the string which is lexicographically smallest and not a subsequence of the given string S. Examples: Input: S = "abcdefghijklmnopqrstuvwxyz"Output: aaExplanation:String "aa" is the lexicographically smallest string which is not present in the given string as a
5 min read
Lexicographic smallest permutation of a String containing the second String as a Substring
Given two strings str1 and str2, the task is to find the lexicographic smallest permutation of str1 that contains str2 as a substring. Note: Assume that the solution always exists. Example: Input: str1 = âababâ, str2 = âabâOutput: âaabbâExplanation: The Lexicographically smallest permutation of stri
8 min read
Find Binary String of size at most 3N containing at least 2 given strings of size 2N as subsequences
Given three binary strings a, b, and c each having 2*N characters each, the task is to find a string having almost 3*N characters such that at least two of the given three strings occur as its one of the subsequence. Examples: Input: a = "00", b = "11", c = "01"Output: "010"Explanation: The strings
11 min read
Minimum size lexicographically smallest string which is not a substring of given string
Given a string s, the task is to find the lexicographically smallest string of minimum characters that do not exist as a substring in S. Examples: Input: S = "aabacdefghijklmnopqrstuvwxyz"Output: adExplanation: All the single digit strings from [a-z] occur in the given string and in two character st
7 min read
Subsequences of given string consisting of non-repeating characters
Given a string str of length N, the task is to print all possible distinct subsequences of the string str which consists of non-repeating characters only. Examples: Input: str = "abac" Output: a ab abc ac b ba bac bc c Explanation: All possible distinct subsequences of the strings are { a, aa, aac,
7 min read