📌  相关文章
📜  最小化从给定字符串中挑选 K 个唯一子序列的总成本

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

最小化从给定字符串中挑选 K 个唯一子序列的总成本

给定一个长度为N的字符串S和一个正整数K ,任务是找到选择给定字符串SK个唯一子序列的最小总成本,使得选择一个子序列的成本为(S 的长度 -该子序列的长度子序列) 。如果不可能选择K个唯一子序列,则打印“ -1 ”。

例子:

朴素方法:最简单的方法是生成给定字符串S的所有可能的不同子序列,并选择K个最大可能长度的唯一子序列。选择K 个子序列后,结果将是 ( N*K – 所有选择的 K 个子序列的长度之和。)

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

高效方法:上述方法也可以通过使用动态规划进行优化。这个想法是初始化二维 DP 数组,使得dp[i[j]表示长度为i的唯一子序列的长度总和,该子序列以字符j结尾。现在,在预先计算之后,选择那些长度和最大的子序列的K长度。请按照以下步骤解决问题:

  • 将变量ans初始化为0。
  • 用值0初始化一个二维数组dp[N+1][128]
  • 使用变量i遍历范围[0, N)并执行以下任务:
    • 使用变量len迭代步骤[i+1, 1)并执行以下任务:
      • dp[len][s[i]]设置为累积(dp[len – 1].begin(), dp[len – 1].end(), 0L)。
    • dp[1][s[i]]设置为1。
  • 用值0初始化向量v[N+1]
  • v[0]设置为1。
  • 使用变量i遍历范围[1, N]并执行以下任务:
    • v[i]设置为累积 (dp[i].begin(), dp[i].end(), 0L)。
  • 反转向量v[]。
  • 使用变量i遍历 for 循环并执行以下任务:
    • 初始化一个变量可以取kv[i] 的最小值。
    • k中减去值cantake
    • ans的值增加i*cantake。
  • 执行上述步骤后,打印ans的值作为答案。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to find the minimum cost to
// find K unique subsequences
int minimumCost(string s, int k)
{
    int N = s.length(), ans = 0;
 
    // Stores the dp states
    vector > dp(
        N + 1, vector(128, 0));
 
    // Precompute the dp states
    for (int i = 0; i < N; i++) {
 
        // Find the sum of length
        // of subsequence of length len
        // ending at index S[i]
        for (int len = i + 1; len > 1;
             len--) {
            dp[len][s[i]]
                = (accumulate(dp[len - 1].begin(),
                              dp[len - 1].end(), 0L));
        }
 
        // Sum of length of subsequence
        // of length 1
        dp[1][s[i]] = 1;
    }
    vector v(N + 1, 0);
 
    v[0] = 1;
 
    for (int i = 1; i <= N; i++) {
        v[i] += accumulate(dp[i].begin(),
                           dp[i].end(), 0L);
    }
    reverse(v.begin(), v.end());
    for (int i = 0; i < v.size() and k > 0; i++) {
        long long cantake = min(k, v[i]);
        k -= cantake;
        ans += (i * cantake);
    }
    return k > 0 ? -1 : ans;
}
 
// Driver Code
int main()
{
    string S = "efef";
    int K = 4;
    cout << minimumCost(S, K);
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
class GFG{
 
  // Function to find the minimum cost to
  // find K unique subsequences
  static int minimumCost(String s, int k)
  {
    int N = s.length(), ans = 0;
 
    // Stores the dp states
    int [][]dp = new int[N+1][128];
 
    // Precompute the dp states
    for (int i = 0; i < N; i++) {
 
      // Find the sum of length
      // of subsequence of length len
      // ending at index S[i]
      for (int len = i + 1; len > 1;
           len--) {
        dp[len][s.charAt(i)]
          = (accumulate(dp[len - 1],0,dp[len - 1].length));
      }
 
      // Sum of length of subsequence
      // of length 1
      dp[1][s.charAt(i)] = 1;
    }
    int []v = new int[N + 1];
 
    v[0] = 1;
 
    for (int i = 1; i <= N; i++) {
      v[i] += (accumulate(dp[i],0,dp[i].length));
    }
    v = reverse(v);
    for (int i = 0; i < v.length && k > 0; i++) {
      long cantake = Math.min(k, v[i]);
      k -= cantake;
      ans += (i * cantake);
    }
    return k > 0 ? -1 : ans;
  }
  static int[] reverse(int a[]) {
    int i, n = a.length, t;
    for (i = 0; i < n / 2; i++) {
      t = a[i];
      a[i] = a[n - i - 1];
      a[n - i - 1] = t;
    }
    return a;
  }
  static int accumulate(int[] arr, int start, int end){
    int sum=0;
    for(int i= 0; i < arr.length; i++)
      sum+=arr[i];
    return sum;
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    String S = "efef";
    int K = 4;
    System.out.print(minimumCost(S, K));
  }
}
 
// This code contributed by shikhasingrajput


Python3
# python3 code for the above approach
 
 
def accumulate(a):
    total = 0
    for i in a:
        total += i
 
    return total
 
 
# Function to find the minimum cost to
# find K unique subsequences
def minimumCost(s, k):
    N, ans = len(s), 0
 
    # Stores the dp states
    dp = [[0 for _ in range(128)] for _ in range(N + 1)]
 
    # Precompute the dp states
    for i in range(0, N):
 
        # Find the sum of length
        # of subsequence of length len
        # ending at index S[i]
        for le in range(i + 1, 1, -1):
 
            dp[le][ord(s[i])] = (accumulate(dp[le - 1]))
 
        # Sum of length of subsequence
        # of length 1
        dp[1][ord(s[i])] = 1
 
    v = [0 for _ in range(N + 1)]
 
    v[0] = 1
 
    for i in range(1, N+1):
        v[i] += accumulate(dp[i])
 
    v.reverse()
 
    for i in range(0, len(v), 1):
        if k <= 0:
            break
        cantake = min(k, v[i])
        k -= cantake
        ans += (i * cantake)
 
    return -1 if k > 0 else ans
 
 
# Driver Code
 
if __name__ == "__main__":
 
    S = "efef"
    K = 4
    print(minimumCost(S, K))
 
    # This code is contributed by rakeshsahni


Javascript


C#
// C# program for the above approach
using System;
public class GFG
{
 
  public static int[] GetRow(int[,] matrix, int row)
  {
    var rowLength = matrix.GetLength(1);
    var rowVector = new int[rowLength];
 
    for (var i = 0; i < rowLength; i++)
      rowVector[i] = matrix[row, i];
 
    return rowVector;
  }
   
  // Function to find the minimum cost to
  // find K unique subsequences
  static int minimumCost(String s, int k) {
    int N = s.Length, ans = 0;
 
    // Stores the dp states
    int[,] dp = new int[N + 1,128];
 
    // Precompute the dp states
    for (int i = 0; i < N; i++) {
 
      // Find the sum of length
      // of subsequence of length len
      // ending at index S[i]
      for (int len = i + 1; len > 1; len--) {
        int[] row = GetRow(dp,len-1);
        dp[len,s[i]] = (accumulate(row, 0, row.Length));
      }
 
      // Sum of length of subsequence
      // of length 1
      dp[1,s[i]] = 1;
    }
    int[] v = new int[N + 1];
 
    v[0] = 1;
 
    for (int i = 1; i <= N; i++) {
      int[] row = GetRow(dp,i);
      v[i] += (accumulate(row, 0, row.Length));
    }
    v = reverse(v);
    for (int i = 0; i < v.Length && k > 0; i++) {
      long cantake = Math.Min(k, v[i]);
      k -= (int)cantake;
      ans += (int)(i * cantake);
    }
    return k > 0 ? -1 : (int)ans;
  }
 
  static int[] reverse(int []a) {
    int i, n = a.Length, t;
    for (i = 0; i < n / 2; i++) {
      t = a[i];
      a[i] = a[n - i - 1];
      a[n - i - 1] = t;
    }
    return a;
  }
 
  static int accumulate(int[] arr, int start, int end) {
    int sum = 0;
    for (int i = 0; i < arr.Length; i++)
      sum += arr[i];
    return sum;
  }
 
  // Driver Code
  public static void Main(String[] args) {
    String S = "efef";
    int K = 4;
    Console.Write(minimumCost(S, K));
  }
}
 
// This code is contributed by umadevi9616



输出
3

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