Welcome to Subscribe On Youtube
2842. Count K-Subsequences of a String With Maximum Beauty
Description
You are given a string s and an integer k.
A k-subsequence is a subsequence of s, having length k, and all its characters are unique, i.e., every character occurs once.
Let f(c) denote the number of times the character c occurs in s.
The beauty of a k-subsequence is the sum of f(c) for every character c in the k-subsequence.
For example, consider s = "abbbdd" and k = 2:
f('a') = 1,f('b') = 3,f('d') = 2- Some k-subsequences of
sare:"abbbdd"->"ab"having a beauty off('a') + f('b') = 4"abbbdd"->"ad"having a beauty off('a') + f('d') = 3"abbbdd"->"bd"having a beauty off('b') + f('d') = 5
Return an integer denoting the number of k-subsequences whose beauty is the maximum among all k-subsequences. Since the answer may be too large, return it modulo 109 + 7.
A subsequence of a string is a new string formed from the original string by deleting some (possibly none) of the characters without disturbing the relative positions of the remaining characters.
Notes
f(c)is the number of times a charactercoccurs ins, not a k-subsequence.- Two k-subsequences are considered different if one is formed by an index that is not present in the other. So, two k-subsequences may form the same string.
Example 1:
Input: s = "bcca", k = 2
Output: 4
Explanation: From s we have f('a') = 1, f('b') = 1, and f('c') = 2.
The k-subsequences of s are:
bcca having a beauty of f('b') + f('c') = 3
bcca having a beauty of f('b') + f('c') = 3
bcca having a beauty of f('b') + f('a') = 2
bcca having a beauty of f('c') + f('a') = 3
bcca having a beauty of f('c') + f('a') = 3
There are 4 k-subsequences that have the maximum beauty, 3.
Hence, the answer is 4.
Example 2:
Input: s = "abbcd", k = 4
Output: 2
Explanation: From s we have f('a') = 1, f('b') = 2, f('c') = 1, and f('d') = 1.
The k-subsequences of s are:
abbcd having a beauty of f('a') + f('b') + f('c') + f('d') = 5
abbcd having a beauty of f('a') + f('b') + f('c') + f('d') = 5
There are 2 k-subsequences that have the maximum beauty, 5.
Hence, the answer is 2.
Constraints:
1 <= s.length <= 2 * 1051 <= k <= s.lengthsconsists only of lowercase English letters.
Solutions
Solution 1: Greedy + Combinatorial Mathematics
First, we use a hash table $f$ to count the occurrence of each character in the string $s$, i.e., $f[c]$ represents the number of times character $c$ appears in the string $s$.
Since a $k$-subsequence is a subsequence of length $k$ in the string $s$ with unique characters, if the number of different characters in $f$ is less than $k$, then there is no $k$-subsequence, and we can directly return $0$.
Otherwise, to maximize the beauty value of the $k$-subsequence, we need to make characters with high beauty values appear as much as possible in the $k$-subsequence. Therefore, we can sort the values in $f$ in reverse order to get an array $vs$.
We denote the occurrence of the $k$th character in the array $vs$ as $val$, and there are $x$ characters with an occurrence of $val$.
Then we first find out the characters with occurrences greater than $val$, multiply the occurrences of each character to get the initial answer $ans$, and update the remaining number of characters to be selected to $k$. We need to select $k$ characters from $x$ characters, so the answer needs to be multiplied by the combination number $C_x^k$, and finally multiplied by $val^k$, i.e., $ans = ans \times C_x^k \times val^k$.
Note that we need to use fast power and modulo operations here.
The time complexity is $O(n)$, and the space complexity is $O(|\Sigma|)$. Here, $n$ is the length of the string, and $\Sigma$ is the character set. In this problem, the character set is lowercase letters, so $|\Sigma| = 26$.
-
class Solution { private final int mod = (int) 1e9 + 7; public int countKSubsequencesWithMaxBeauty(String s, int k) { int[] f = new int[26]; int n = s.length(); int cnt = 0; for (int i = 0; i < n; ++i) { if (++f[s.charAt(i) - 'a'] == 1) { ++cnt; } } if (cnt < k) { return 0; } Integer[] vs = new Integer[cnt]; for (int i = 0, j = 0; i < 26; ++i) { if (f[i] > 0) { vs[j++] = f[i]; } } Arrays.sort(vs, (a, b) -> b - a); long ans = 1; int val = vs[k - 1]; int x = 0; for (int v : vs) { if (v == val) { ++x; } } for (int v : vs) { if (v == val) { break; } --k; ans = ans * v % mod; } int[][] c = new int[x + 1][x + 1]; for (int i = 0; i <= x; ++i) { c[i][0] = 1; for (int j = 1; j <= i; ++j) { c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod; } } ans = ((ans * c[x][k]) % mod) * qpow(val, k) % mod; return (int) ans; } private long qpow(long a, int n) { long ans = 1; for (; n > 0; n >>= 1) { if ((n & 1) == 1) { ans = ans * a % mod; } a = a * a % mod; } return ans; } } -
class Solution { public: int countKSubsequencesWithMaxBeauty(string s, int k) { int f[26]{}; int cnt = 0; for (char& c : s) { if (++f[c - 'a'] == 1) { ++cnt; } } if (cnt < k) { return 0; } vector<int> vs(cnt); for (int i = 0, j = 0; i < 26; ++i) { if (f[i]) { vs[j++] = f[i]; } } sort(vs.rbegin(), vs.rend()); const int mod = 1e9 + 7; long long ans = 1; int val = vs[k - 1]; int x = 0; for (int v : vs) { x += v == val; } for (int v : vs) { if (v == val) { break; } --k; ans = ans * v % mod; } int c[x + 1][x + 1]; memset(c, 0, sizeof(c)); for (int i = 0; i <= x; ++i) { c[i][0] = 1; for (int j = 1; j <= i; ++j) { c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; } } auto qpow = [&](long long a, int n) { long long ans = 1; for (; n; n >>= 1) { if (n & 1) { ans = ans * a % mod; } a = a * a % mod; } return ans; }; ans = (ans * c[x][k] % mod) * qpow(val, k) % mod; return ans; } }; -
class Solution: def countKSubsequencesWithMaxBeauty(self, s: str, k: int) -> int: f = Counter(s) if len(f) < k: return 0 mod = 10**9 + 7 vs = sorted(f.values(), reverse=True) val = vs[k - 1] x = vs.count(val) ans = 1 for v in vs: if v == val: break k -= 1 ans = ans * v % mod ans = ans * comb(x, k) * pow(val, k, mod) % mod return ans -
func countKSubsequencesWithMaxBeauty(s string, k int) int { f := [26]int{} cnt := 0 for _, c := range s { f[c-'a']++ if f[c-'a'] == 1 { cnt++ } } if cnt < k { return 0 } vs := []int{} for _, x := range f { if x > 0 { vs = append(vs, x) } } sort.Slice(vs, func(i, j int) bool { return vs[i] > vs[j] }) const mod int = 1e9 + 7 ans := 1 val := vs[k-1] x := 0 for _, v := range vs { if v == val { x++ } } for _, v := range vs { if v == val { break } k-- ans = ans * v % mod } c := make([][]int, x+1) for i := range c { c[i] = make([]int, x+1) c[i][0] = 1 for j := 1; j <= i; j++ { c[i][j] = (c[i-1][j-1] + c[i-1][j]) % mod } } qpow := func(a, n int) int { ans := 1 for ; n > 0; n >>= 1 { if n&1 == 1 { ans = ans * a % mod } a = a * a % mod } return ans } ans = (ans * c[x][k] % mod) * qpow(val, k) % mod return ans } -
function countKSubsequencesWithMaxBeauty(s: string, k: number): number { const f: number[] = new Array(26).fill(0); let cnt = 0; for (const c of s) { const i = c.charCodeAt(0) - 97; if (++f[i] === 1) { ++cnt; } } if (cnt < k) { return 0; } const mod = BigInt(10 ** 9 + 7); const vs: number[] = f.filter(v => v > 0).sort((a, b) => b - a); const val = vs[k - 1]; const x = vs.filter(v => v === val).length; let ans = 1n; for (const v of vs) { if (v === val) { break; } --k; ans = (ans * BigInt(v)) % mod; } const c: number[][] = new Array(x + 1).fill(0).map(() => new Array(k + 1).fill(0)); for (let i = 0; i <= x; ++i) { c[i][0] = 1; for (let j = 1; j <= Math.min(i, k); ++j) { c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % Number(mod); } } const qpow = (a: bigint, n: number): bigint => { let ans = 1n; for (; n; n >>>= 1) { if (n & 1) { ans = (ans * a) % BigInt(mod); } a = (a * a) % BigInt(mod); } return ans; }; ans = (((ans * BigInt(c[x][k])) % mod) * qpow(BigInt(val), k)) % mod; return Number(ans); }