Skip to content

3333. Find the Original Typed String II

Description

Alice is attempting to type a specific string on her computer. However, she tends to be clumsy and may press a key for too long, resulting in a character being typed multiple times.

You are given a string word, which represents the final output displayed on Alice's screen. You are also given a positive integer k.

Return the total number of possible original strings that Alice might have intended to type, if she was trying to type a string of size at least k.

Since the answer may be very large, return it modulo 109 + 7.

 

Example 1:

Input: word = "aabbccdd", k = 7

Output: 5

Explanation:

The possible strings are: "aabbccdd", "aabbccd", "aabbcdd", "aabccdd", and "abbccdd".

Example 2:

Input: word = "aabbccdd", k = 8

Output: 1

Explanation:

The only possible string is "aabbccdd".

Example 3:

Input: word = "aaabbb", k = 3

Output: 8

 

Constraints:

  • 1 <= word.length <= 5 * 105
  • word consists only of lowercase English letters.
  • 1 <= k <= 2000

 

Solutions

Solution: Dynamic Programming

  • Time complexity: O(groups.length*k+n)
  • Space complexity: O(groups.length+k)

 

JavaScript

js
/**
 * @param {string} word
 * @param {number} k
 * @return {number}
 */
const possibleStringCount = function (word, k) {
  const MODULO = BigInt(10 ** 9 + 7);
  const n = word.length;
  const groups = [];
  let group = 1n;

  for (let index = 1; index <= n; index++) {
    if (word[index] === word[index - 1]) {
      group += 1n;
    } else {
      groups.push(group);
      group = 1n;
    }
  }

  const combinations = groups.reduce((total, group) => (total * group) % MODULO, 1n);

  if (groups.length >= k) return Number(combinations);

  let dp = Array.from({ length: k + 1 }, () => 0n);

  dp[1] = 1n;

  for (const [index, group_] of groups.entries()) {
    const nextDp = new Array(k + 1).fill(0n);
    const group = Number(group_);
    let sumCount = 0n;

    for (let len = index + 1; len <= k; len++) {
      nextDp[len] = (nextDp[len] + sumCount) % MODULO;
      sumCount = (sumCount + dp[len]) % MODULO;

      if (len > group) {
        const overCount = dp[len - group];

        sumCount = (sumCount - overCount + MODULO) % MODULO;
      }
    }

    dp = nextDp;
  }

  const invalidCombinations = dp.reduce((total, count) => (total + count) % MODULO);

  return Number((combinations - invalidCombinations + MODULO) % MODULO);
};

Released under the MIT license