📌  相关文章
📜  从字符串 A 中删除字符以将任何子序列作为字符串 B 删除的最低成本

📅  最后修改于: 2022-05-13 01:56:04.433000             🧑  作者: Mango

从字符串 A 中删除字符以将任何子序列作为字符串 B 删除的最低成本

给定两个大小分别为NM的字符串AB ,其中B是子序列 A和大小为N的数组arr[] ,其中arr[i] 从字符串A中删除第 i 个字符的成本。任务是找到从A中删除字符的最小成本,使得删除后A的任何子序列都与B相同。

例子:

方法:解决问题的简单方法是使用递归并根据以下想法找到AB之间的公共子序列:

按照下面提到的步骤来实现这个想法:

  • 使用指针i递归遍历字符串A并保持指针j指向B
  • 在每个递归函数中:
    • 如果到达字符串的末尾,如果删除了任何字符(由已删除元素的计数器检查),则返回 0,否则返回高正值。
    • 如果A[i] = B[j]有两种选择:
      • 删除A[i]并添加成本arr[i]以回答并递归调用下一个元素。
      • 保持A[i]并继续前进。
    • 否则继续前进,直到A[i]匹配B[i]
    • 从每个递归调用中返回上述两种情况中的最小成本。
  • 返回最小成本作为答案。

时间复杂度: O(2 M )
辅助空间: O(1)

高效方法:上述方法的时间可以根据以下思想使用动态规划进一步优化:

下面是上述方法的实现。

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Array for memoization
int dp[101][101][2];
 
// Recursive function to calculate
// the minimum cost using dynamic programming
int minCostUtil(string& a, int n,
                string& b, int m,
                vector& c, int removed)
{
 
    // Base case reached the end of string
    if (n == 0 || m == 0) {
 
        // Removed 0 characters
        // return high (+)ve value
        if (removed == 0)
            return 99999;
        return 0;
    }
 
    // Return pre-calculated value
    if (dp[n][m][removed > 0 ? 1 : 0] != -1)
        return dp[n][m][removed > 0 ? 1 : 0];
 
    // If characters match return the minimum of
    // 1. Removing the character from A and
    // adding the cost
    // 2. Moving forward to remove some other
    // character and decrease the counter as
    // this character will not be removed.
    if (a[n - 1] == b[m - 1]) {
        dp[n][m][removed > 0 ? 1 : 0]
            = min(c[n - 1]
                      + minCostUtil(a, n - 1,
                                    b, m, c, removed),
                  minCostUtil(a, n - 1, b, m - 1,
                              c, removed - 1));
        return dp[n][m][removed > 0 ? 1 : 0];
    }
 
    // If no match then move through string
    // A and try removing some other
    // character which matches, i.e can be
    // part of the subsequence that is equal to B
    else
        return dp[n][m][removed > 0 ? 1 : 0]
               = minCostUtil(a, n - 1,
                             b, m, c, removed);
}
 
// Function to calculate minimum cost
int minCost(string& a, string& b,
            vector& c)
{
    memset(dp, -1, sizeof(dp));
    return minCostUtil(a, a.size(), b,
                       b.size(), c, b.size());
}
 
// Driver code
int main()
{
    string A = "abccdabccdabccd";
    string B = "bccd";
    vector arr = { 1, 2, 3, 4, 5,
                        6, 7, 8, 9, 10,
                        11, 12, 13, 14, 15 };
 
    cout << minCost(A, B, arr);
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
public class GFG {
 
  // Array for memoization
  static int dp[][][] = new int[101][101][2];
 
  // Recursive function to calculate
  // the minimum cost using dynamic programming
  static int minCostUtil(String a, int n, String b, int m,
                         int[] c, int removed)
  {
 
    // Base case reached the end of string
    if (n == 0 || m == 0) {
 
      // Removed 0 characters
      // return high (+)ve value
      if (removed == 0)
        return 99999;
      return 0;
    }
 
    // Return pre-calculated value
    if (dp[n][m][removed > 0 ? 1 : 0] != -1)
      return dp[n][m][removed > 0 ? 1 : 0];
 
    // If characters match return the minimum of
    // 1. Removing the character from A and
    // adding the cost
    // 2. Moving forward to remove some other
    // character and decrease the counter as
    // this character will not be removed.
    if (a.charAt(n - 1) == b.charAt(m - 1)) {
      dp[n][m][removed > 0 ? 1 : 0]
        = Math.min(c[n - 1]
                   + minCostUtil(a, n - 1, b, m,
                                 c, removed),
                   minCostUtil(a, n - 1, b, m - 1,
                               c, removed - 1));
      return dp[n][m][removed > 0 ? 1 : 0];
    }
 
    // If no match then move through string
    // A and try removing some other
    // character which matches, i.e can be
    // part of the subsequence that is equal to B
    else
      return dp[n][m][removed > 0 ? 1 : 0]
      = minCostUtil(a, n - 1, b, m, c, removed);
  }
 
  // Function to calculate minimum cost
  static int minCost(String a, String b, int[] c)
  {
    for (int i = 0; i < 101; i++) {
      for (int j = 0; j < 101; j++) {
        for (int k = 0; k < 2; k++) {
          dp[i][j][k] = -1;
        }
      }
    }
    return minCostUtil(a, a.length(), b, b.length(), c,
                       b.length());
  }
 
  // Driver code
  public static void main(String args[])
  {
    String A = "abccdabccdabccd";
    String B = "bccd";
    int[] arr = { 1, 2,  3,  4,  5,  6,  7, 8,
                 9, 10, 11, 12, 13, 14, 15 };
 
    System.out.print(minCost(A, B, arr));
  }
}
 
// This code is contributed by Samim Hossain Mondal.


C#
// C# program for the above approach
using System;
 
public class GFG{
 
  // Array for memoization
  static int[,,] dp = new int[101, 101, 2];
 
  // Recursive function to calculate
  // the minimum cost using dynamic programming
  static int minCostUtil(string a, int n, string b, int m,
                         int[] c, int removed)
  {
 
    // Base case reached the end of string
    if (n == 0 || m == 0) {
 
      // Removed 0 characters
      // return high (+)ve value
      if (removed == 0)
        return 99999;
      return 0;
    }
 
    // Return pre-calculated value
    if (dp[n, m, removed > 0 ? 1 : 0] != -1)
      return dp[n, m, removed > 0 ? 1 : 0];
 
    // If characters match return the minimum of
    // 1. Removing the character from A and
    // adding the cost
    // 2. Moving forward to remove some other
    // character and decrease the counter as
    // this character will not be removed.
    if (a[n - 1] == b[m - 1]) {
      dp[n, m, removed > 0 ? 1 : 0]
        = Math.Min(c[n - 1]
                   + minCostUtil(a, n - 1, b, m,
                                 c, removed),
                   minCostUtil(a, n - 1, b, m - 1,
                               c, removed - 1));
      return dp[n, m, removed > 0 ? 1 : 0];
    }
 
    // If no match then move through string
    // A and try removing some other
    // character which matches, i.e can be
    // part of the subsequence that is equal to B
    else
      return dp[n, m, removed > 0 ? 1 : 0]
      = minCostUtil(a, n - 1, b, m, c, removed);
  }
 
  // Function to calculate minimum cost
  static int minCost(string a, string b, int[] c)
  {
    for (int i = 0; i < 101; i++) {
      for (int j = 0; j < 101; j++) {
        for (int k = 0; k < 2; k++) {
          dp[i, j, k] = -1;
        }
      }
    }
    return minCostUtil(a, a.Length, b, b.Length, c,
                       b.Length);
  }
 
  // Driver code
  static public void Main (){
 
    string A = "abccdabccdabccd";
    string B = "bccd";
    int[] arr = { 1, 2,  3,  4,  5,  6,  7, 8,
                 9, 10, 11, 12, 13, 14, 15 };
 
    Console.Write(minCost(A, B, arr));
  }
}
 
// This code is contributed by hrithikgarg03188.


Javascript
// JavaScript program for the above approach
 
// Array for memoization
var dp = [];
 
// Recursive function to calculate
// the minimum cost using dynamic programming
function minCostUtil(a, n, b, m, c, removed)
{
    // Base case reached the end of string
    if (n == 0 || m == 0) {
        // Removed 0 characters
        // return high (+)ve value
        if (removed == 0)
            return 99999;
        return 0;
    }
 
    // Return pre-calculated value
    if (dp[n][m][Number(Boolean(removed))] != -1)
        return dp[n][m][(removed > 0) ? 1 : 0];
    // If characters match return the minimum of
    // 1. Removing the character from A and
    // adding the cost
    // 2. Moving forward to remove some other
    // character and decrease the counter as
    // this character will not be removed.
    if (a[n - 1] == b[m - 1]) {
        dp[n][m][(removed > 0) ? 1 : 0] = Math.min(
            c[n - 1]
                + minCostUtil(a, n - 1, b, m, c, removed),
            minCostUtil(a, n - 1, b, m - 1, c,
                        removed - 1));
        return dp[n][m][(removed > 0) ? 1 : 0];
    }
    // If no match then move through string
    // A and try removing some other
    // character which matches, i.e can be
    // part of the subsequence that is equal to B
    else
        return dp[n][m][(removed > 0) ? 1 : 0]
               = minCostUtil(a, n - 1, b, m, c, removed);
}
// Function to calculate minimum cost
 
function minCost(a, b, c)
{
    for (var i = 0; i < 101; i++) {
        dp[i] = [];
        for (var j = 0; j < 101; j++) {
            dp[i].push([]);
            for (var k = 0; k < 2; k++) {
                dp[i][j].push([-1]);
            }
        }
    }
 
    return minCostUtil(a, a.length, b, b.length, c,
                       b.length);
}
 
// Driver code
var A = "abccdabccdabccd";
var B = "bccd";
var arr =
    [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ];
document.write(minCost(A, B, arr));
 
// This code is contributed by phasing17


输出
21

时间复杂度: O(N*M)
辅助空间: O(N*M)