最小化从给定字符串中挑选 K 个唯一子序列的总成本
给定一个长度为N的字符串S和一个正整数K ,任务是找到选择给定字符串S的K个唯一子序列的最小总成本,使得选择一个子序列的成本为(S 的长度 -该子序列的长度子序列) 。如果不可能选择K个唯一子序列,则打印“ -1 ”。
例子:
Input: S = “efef”, K = 4
Output: 3
Explanation: There are 4 subsequences – “efef”, “efe”, “eef” and “fef”.
Hence, the total cost is 0 + 1 + 1 + 1 = 3.
Input: S = “aaaaa”, K = 40
Output: -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。
- 使用变量len迭代步骤[i+1, 1)并执行以下任务:
- 用值0初始化向量v[N+1] 。
- 将v[0]设置为1。
- 使用变量i遍历范围[1, N]并执行以下任务:
- 将v[i]设置为累积 (dp[i].begin(), dp[i].end(), 0L)。
- 反转向量v[]。
- 使用变量i遍历 for 循环并执行以下任务:
- 初始化一个变量可以取k或v[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)