查找包含另一个字符串作为子序列的给定字符串的最小子字符串的长度
给定两个字符串A和B ,任务是找到以B作为子序列的A的最小子字符串。如果A中有多个这样的子字符串,则返回具有最小起始索引的子字符串。
例子 :
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.
朴素方法:解决给定问题的最简单方法是检查字符串B 作为 A 的每个子字符串中的子序列出现。
在这些子串中,答案将是长度最短且索引最小的一个。
时间复杂度: O(N 3 )
辅助空间: O(1)
高效方法:上述方法也可以通过使用动态规划进行优化,因为上述问题具有重叠子问题和最优子结构。子问题可以存储在dp[][]表记忆中,其中dp[i][j]表示在子串A(0…i)中存在一个对应于B(0…j)的子序列,该子序列从索引dp[我][j] 。请按照以下步骤解决问题:
- 初始化一个全局多维数组dp[100][100] ,所有值都为-1 ,存储每个dp状态的结果。
- dp表中的每一列代表字符串B中的一个字符。
- 初始化dp数组的第一列,即将字符串A的字符串前缀中。
- 填充dp表的其余列。对于字符串B中位置'j'的特定字符,检查字符串A中是否存在匹配字符。
- 如果A[i] == B[j] ,则字符串A中所需子字符串的起始索引等于字符串B的前j – 1 个字符与字符串的前i – 1 个字符匹配时的起始索引一个。
- 如果A[i] != B[j] ,则字符串A中所需子字符串的起始索引等于字符串B的前j个字符与字符串A的前i-1 个字符匹配时的起始索引。
- 检查dp表最后一列中的任何值是否大于或等于0 。对于字符串A中的特定索引i ,如果dp[i][b – 1] >= 0 ,则所需的以B作为子序列的子字符串是A[dp[i][b-1] : i] 。用尽可能短的子字符串更新答案。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
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 occurence 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 occurence 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 occurence 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 occurence 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
bced
时间复杂度: O(N 2 )
辅助空间: O(N 2 )