comments | difficulty | edit_url | rating | source | tags | |||||
---|---|---|---|---|---|---|---|---|---|---|
true |
困难 |
2091 |
第 112 场双周赛 Q4 |
|
给你一个字符串 s
和一个整数 k
。
k 子序列指的是 s
的一个长度为 k
的 子序列 ,且所有字符都是 唯一 的,也就是说每个字符在子序列里只出现过一次。
定义 f(c)
为字符 c
在 s
中出现的次数。
k 子序列的 美丽值 定义为这个子序列中每一个字符 c
的 f(c)
之 和 。
比方说,s = "abbbdd"
和 k = 2
,我们有:
f('a') = 1
,f('b') = 3
,f('d') = 2
s
的部分 k 子序列为:"abbbdd"
->"ab"
,美丽值为f('a') + f('b') = 4
"abbbdd"
->"ad"
,美丽值为f('a') + f('d') = 3
"abbbdd"
->"bd"
,美丽值为f('b') + f('d') = 5
请你返回一个整数,表示所有 k 子序列 里面 美丽值 是 最大值 的子序列数目。由于答案可能很大,将结果对 109 + 7
取余后返回。
一个字符串的子序列指的是从原字符串里面删除一些字符(也可能一个字符也不删除),不改变剩下字符顺序连接得到的新字符串。
注意:
f(c)
指的是字符c
在字符串s
的出现次数,不是在 k 子序列里的出现次数。- 两个 k 子序列如果有任何一个字符在原字符串中的下标不同,则它们是两个不同的子序列。所以两个不同的 k 子序列可能产生相同的字符串。
示例 1:
输入:s = "bcca", k = 2
输出:4
解释:s 中我们有 f('a') = 1 ,f('b') = 1 和 f('c') = 2 。
s 的 k 子序列为:
bcca ,美丽值为 f('b') + f('c') = 3
bcca ,美丽值为 f('b') + f('c') = 3
bcca ,美丽值为 f('b') + f('a') = 2
bcca ,美丽值为 f('c') + f('a') = 3
bcca ,美丽值为 f('c') + f('a') = 3
总共有 4 个 k 子序列美丽值为最大值 3 。
所以答案为 4 。
示例 2:
输入:s = "abbcd", k = 4 输出:2 解释:s 中我们有 f('a') = 1 ,f('b') = 2 ,f('c') = 1 和 f('d') = 1 。 s 的 k 子序列为: abbcd ,美丽值为 f('a') + f('b') + f('c') + f('d') = 5 abbcd ,美丽值为 f('a') + f('b') + f('c') + f('d') = 5 总共有 2 个 k 子序列美丽值为最大值 5 。 所以答案为 2 。
提示:
1 <= s.length <= 2 * 105
1 <= k <= s.length
s
只包含小写英文字母。
我们先用哈希表
由于
否则,要使得
我们记数组
那么我们先找出出现次数大于
注意,这里需要用到快速幂,以及取模操作。
时间复杂度
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
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;
}
};
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);
}