Back to all solutions
#2539 - Count the Number of Good Subsequences
Problem Description
A subsequence of a string is good if it is not empty and the frequency of each one of its characters is the same.
Given a string s, return the number of good subsequences of s. Since the answer may be too large, return it modulo 109 + 7.
A subsequence is a string that can be derived from another string by deleting some or no characters without changing the order of the remaining characters.
Solution
/**
* @param {string} s
* @return {number}
*/
var countGoodSubsequences = function(s) {
const MOD = 1e9 + 7;
const n = s.length;
const factorial = new Array(n + 1);
const frequency = new Array(26).fill(0);
let maxFrequency = 0;
for (let i = 0; i < n; i++) {
frequency[s.charCodeAt(i) - 97]++;
}
for (let i = 0; i < 26; i++) {
maxFrequency = Math.max(maxFrequency, frequency[i]);
}
let result = 0n;
for (let k = 1; k <= maxFrequency; k++) {
let current = 1n;
for (let i = 0; i < 26; i++) {
if (frequency[i] > 0) {
current = (current * (1n + combination(frequency[i], k))) % BigInt(MOD);
}
}
result = (result + current - 1n + BigInt(MOD)) % BigInt(MOD);
}
return Number(result);
function computeFactorial(num) {
if (factorial[num] !== undefined) return factorial[num];
if (num === 0) {
factorial[num] = 1n;
} else {
factorial[num] = (computeFactorial(num - 1) * BigInt(num)) % BigInt(MOD);
}
return factorial[num];
}
function modInverse(a) {
let result = 1n;
let base = a % BigInt(MOD);
let exp = BigInt(MOD - 2);
while (exp > 0n) {
if (exp & 1n) result = (result * base) % BigInt(MOD);
base = (base * base) % BigInt(MOD);
exp >>= 1n;
}
return result;
}
function combination(n, k) {
if (n < k) return 0n;
if (n === k) return 1n;
let result = computeFactorial(n);
result = (result * modInverse(computeFactorial(k))) % BigInt(MOD);
result = (result * modInverse(computeFactorial(n - k))) % BigInt(MOD);
return result;
}
};