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
s
are:"abbbdd"
-> "ab"
having a beauty of f('a') + f('b') = 4
"abbbdd"
-> "ad"
having a beauty of f('a') + f('d') = 3
"abbbdd"
-> "bd"
having a beauty of f('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 character c
occurs in s
, 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 * 105
1 <= k <= s.length
s
consists 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$.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| 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
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
| 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;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
| 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;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
| 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
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| 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);
}
|