Find the Original Typed String II solution and explanation
9 more videos on this problem
Find the Original Typed String II | Multiple Approaches | Detailed | Leetcode 3333 |codestorywithMIKcodestorywithMIK · 1:12:05 · 16K views
Find the Original Typed String II | Leetcode 3333Techdose · 44:06 · 3K views
Leetcode 3333. Find the Original Typed String II | Group By + Prefix Sum + DP Solution ExplainedStatLearn Tech · 29:58 · 2K views
3333. Find the Original Typed String II | Leetcode Daily - PythonLeetcode Daily · 7:01 · 2K views
Find the Original Typed String II | LeetCode 3333 - Pythonimpoldev · 21:29 · 2K views
Daily Leetcode #1919: Jul 02, 2025 - 3333. Find the Original Typed String IIProgramming Live with Larry · 1:43:56 · 2K views
LeetCode 3333 - Find the Original Typed String II | Hard Level DSA Explained | Aslam CodingAslam Coding · 16:42 · 1K views
Leetcode 3333. Find the Original Typed String II | DP + Prefix Sum Explained Step-by-StepExpertFunda · 39:52 · 1K views
[English] 3333. Find the Original Typed String II Q4 Biweekly 142 [Leetcode Hard]Romain Lhotte · 20:34 · 903 views
3333. Find the Original Typed String II (Leetcode Hard)Programming Live with Larry · 1:04:00 · 821 views
The problem
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 * 105wordconsists only of lowercase English letters.1 <= k <= 2000
Approach overview
Problem Overview: You are given a typed string where characters may appear multiple times because of long key presses. Each group of identical characters could represent fewer presses in the original string. The task is to count how many possible original strings could produce the typed result while satisfying a minimum length constraint k.
Approach 1: Dynamic Programming with Prefix Sum Optimization (O(m · k) time, O(k) space)
Start by compressing the typed string into groups of consecutive characters. For example, aaabb becomes counts [3,2]. If a group has length g, the original string could contain between 1 and g copies of that character. Let dp[j] represent the number of ways to build an original string of length j using processed groups. For each group, transition by adding between 1 and g characters. Direct transitions would be expensive, so prefix sums are used to compute range sums efficiently when updating the DP array.
The key observation: the total combinations from all groups is simply the product of their sizes, but some produce strings shorter than k. The DP tracks counts for lengths < k. Subtract these from the total combinations to get the number of valid originals with length at least k. This approach combines dynamic programming with prefix sum range aggregation to keep updates efficient.
Approach 2: Suffix Array Technique (O(n log n) time, O(n) space)
A suffix-array-based method analyzes repeated character structure directly from the string. By constructing a suffix array and LCP (Longest Common Prefix) array, you can efficiently detect stretches where characters repeat and reason about how many valid contractions of the typed string are possible. These repeated segments correspond to the same groups used in the DP solution. Once the repetition boundaries are identified, you compute the number of valid reductions per segment and combine them while enforcing the minimum length constraint.
This technique relies heavily on advanced string processing structures such as suffix arrays and LCP arrays. It is more implementation-heavy but performs well when working with large strings or when repetition structure must be extracted efficiently from raw text.
Recommended for interviews: The dynamic programming solution with prefix sums is the expected approach. It demonstrates strong reasoning about combinatorics and efficient DP transitions. A brute-force enumeration of all possible contractions quickly becomes exponential, so showing the DP formulation and prefix-sum optimization signals solid algorithmic maturity.
Approach 1: Dynamic Programming Approach
In this approach, we use dynamic programming to calculate the number of possible original strings Alice intended to type. We will focus on the concept of reducing consecutive duplicate characters in different ways while maintaining a valid length. We'll employ a DP table where each entry represents the number of ways to achieve a certain length of the original string from the current character.
MOD = 10**9 + 7
def possible_original_strings(word, k):
n = len(word)
dp = [0] * (n + 1)
dp[n] = 1
for i in range(n - 1, -1, -1):
dp[i] = dp[i + 1]
if i < n - 1 and word[i] == word[i + 1]:
dp[i] = (dp[i] + dp[i + 2]) % MOD
return sum(dp[i] for i in range(k, n + 1)) % MOD
# Example usage
word = "aabbccdd"
k = 7
print(possible_original_strings(word, k))const MOD = 1e9 + 7;
function possibleOriginalStrings(word, k) {
const n = word.length;
const dp = Array(n + 1).fill(0);
dp[n] = 1;
for (let i = n - 1; i >= 0; i--) {
dp[i] = dp[i + 1];
if (i < n - 1 && word[i] === word[i + 1]) {
dp[i] = (dp[i] + dp[i + 2]) % MOD;
}
}
let result = 0;
for (let i = k; i <= n; i++) {
result = (result + dp[i]) % MOD;
}
return result;
}
// Example usage
const word = "aabbccdd";
const k = 7;
console.log(possibleOriginalStrings(word, k));This solution uses a dynamic programming technique, where dp[i] represents the number of ways to transform the substring starting at index i into valid original strings. We iterate over the word from back to front, updating the dp array based on whether characters can be combined. We then sum the dp values from k to n (inclusive) to get the total possible strings of at least length k.
Time Complexity: O(n), where n is the length of the word. We traverse the string linearly.
Space Complexity: O(n), due to the additional storage used for the dp array.
Approach 2: Suffix Array Technique
This approach leverages suffix arrays to handle large scale string operations efficiently. The key idea is creating suffix arrays to help quickly calculate the possible original string counts using combinations from the given string `word`. However, given the constraints, this method may be less efficient compared to dynamic programming for this problem size.
#include <iostream>
#include <vector>
using namespace std;
const int MOD = 1e9 + 7;
int possibleOriginalStrings(const string &word, int k) {
int n = word.size();
vector<int> dp(n + 1, 0);
dp[n] = 1;
for (int i = n - 1; i >= 0; i--) {
dp[i] = dp[i + 1];
if (i < n - 1 && word[i] == word[i + 1]) {
dp[i] = (dp[i] + dp[i + 2]) % MOD;
}
}
int result = 0;
for (int i = k; i <= n; i++) {
result = (result + dp[i]) % MOD;
}
return result;
}
int main() {
string word = "aabbccdd";
int k = 7;
cout << possibleOriginalStrings(word, k) << endl;
return 0;
}#include <stdio.h>
#define MOD 1000000007
int possibleOriginalStrings(const char *word, int k) {
int n = strlen(word);
int dp[n + 1];
dp[n] = 1;
for (int i = n - 1; i >= 0; i--) {
dp[i] = dp[i + 1];
if (i < n - 1 && word[i] == word[i + 1]) {
dp[i] = (dp[i] + (i + 2 < n ? dp[i + 2] : 1)) % MOD;
}
}
int result = 0;
for (int i = k; i <= n; i++) {
result = (result + dp[i]) % MOD;
}
return result;
}
int main() {
const char *word = "aabbccdd";
int k = 7;
printf("%d\n", possibleOriginalStrings(word, k));
return 0;
}This C++ version mirrors C and Python approaches, applying suffix-like calculations to optimize the count of possible original strings. Through leveraging uptakes for merging identical sequential characters, the result is fine-tuned to include all configurations starting from length k, ensuring modulo 10^9 + 7 arithmetic is respected to handle large numbers efficiently.
Time Complexity: O(n), covers full traversal of the input word.
Space Complexity: O(n), corresponding to the dp array allocation.
Approach 3: Dynamic Programming + Prefix Sum
For the constraint that the length is at least k, we can split it into two subproblems:
- Without length restriction, for each group of consecutive identical characters, we can choose any number from
1to the length of the group. Let the number of ways bea. - For length less than
k, let the number of ways beb.
Thus, the final answer is a - b.
We can group consecutive identical characters in the string word. Since at least one character must be chosen from each group, if a group has more than 0 remaining selectable characters, we add it to an array nums. After initially selecting one character from each group, we update the remaining required character count k.
If k < 1, it means that after selecting one character from each group, the requirement of length at least k is already satisfied, so the answer is a.
Otherwise, we need to calculate the value of b. We use a 2D array f, where f[i][j] represents the number of ways to select j characters from the first i groups. Initially, f[0][0] = 1, meaning there is 1 way to select 0 characters from 0 groups. Then b = sum_{j=0}^{k-1} f[m][j], where m is the length of nums. The answer is a - b.
Consider the transition equation for f[i][j]. For the i-th group of characters, suppose its remaining length is x. For each j, we can enumerate the number of characters l chosen from this group, where l \in [0, min(x, j)]. Then, f[i][j] can be transferred from f[i-1][j-l]. We can use prefix sums to optimize this transition.
The time complexity is O(n + k^2), and the space complexity is O(k^2), where n is the length of the string word.
class Solution {
public int possibleStringCount(String word, int k) {
final int mod = (int) 1e9 + 7;
List<Integer> nums = new ArrayList<>();
long ans = 1;
int cur = 0;
int n = word.length();
for (int i = 0; i < n; i++) {
cur++;
if (i == n - 1 || word.charAt(i) != word.charAt(i + 1)) {
if (cur > 1) {
if (k > 0) {
nums.add(cur - 1);
}
ans = ans * cur % mod;
}
cur = 0;
k--;
}
}
if (k < 1) {
return (int) ans;
}
int m = nums.size();
int[][] f = new int[m + 1][k];
f[0][0] = 1;
for (int i = 1; i <= m; i++) {
int x = nums.get(i - 1);
long[] s = new long[k + 1];
for (int j = 0; j < k; j++) {
s[j + 1] = (s[j] + f[i - 1][j]) % mod;
}
for (int j = 0; j < k; j++) {
int l = Math.max(0, j - x);
f[i][j] = (int) ((s[j + 1] - s[l] + mod) % mod);
}
}
long sum = 0;
for (int j = 0; j < k; j++) {
sum = (sum + f[m][j]) % mod;
}
return (int) ((ans - sum + mod) % mod);
}
}function possibleStringCount(word: string, k: number): number {
const mod = 1_000_000_007;
const nums: number[] = [];
let ans = 1;
let cur = 0;
const n = word.length;
for (let i = 0; i < n; i++) {
cur++;
if (i === n - 1 || word[i] !== word[i + 1]) {
if (cur > 1) {
if (k > 0) {
nums.push(cur - 1);
}
ans = (ans * cur) % mod;
}
cur = 0;
k--;
}
}
if (k < 1) {
return ans;
}
const m = nums.length;
const f: number[][] = Array.from({ length: m + 1 }, () => Array(k).fill(0));
f[0][0] = 1;
for (let i = 1; i <= m; i++) {
const x = nums[i - 1];
const s: number[] = Array(k + 1).fill(0);
for (let j = 0; j < k; j++) {
s[j + 1] = (s[j] + f[i - 1][j]) % mod;
}
for (let j = 0; j < k; j++) {
const l = Math.max(0, j - x);
f[i][j] = (s[j + 1] - s[l] + mod) % mod;
}
}
let sum = 0;
for (let j = 0; j < k; j++) {
sum = (sum + f[m][j]) % mod;
}
return (ans - sum + mod) % mod;
}func possibleStringCount(word string, k int) int {
const mod = 1_000_000_007
nums := []int{}
ans := 1
cur := 0
n := len(word)
for i := 0; i < n; i++ {
cur++
if i == n-1 || word[i] != word[i+1] {
if cur > 1 {
if k > 0 {
nums = append(nums, cur-1)
}
ans = ans * cur % mod
}
cur = 0
k--
}
}
if k < 1 {
return ans
}
m := len(nums)
f := make([][]int, m+1)
for i := range f {
f[i] = make([]int, k)
}
f[0][0] = 1
for i := 1; i <= m; i++ {
x := nums[i-1]
s := make([]int, k+1)
for j := 0; j < k; j++ {
s[j+1] = (s[j] + f[i-1][j]) % mod
}
for j := 0; j < k; j++ {
l := j - x
if l < 0 {
l = 0
}
f[i][j] = (s[j+1] - s[l] + mod) % mod
}
}
sum := 0
for j := 0; j < k; j++ {
sum = (sum + f[m][j]) % mod
}
return (ans - sum + mod) % mod
}Complexity comparison
| Approach | Complexity |
|---|---|
| Dynamic Programming Approach | Time Complexity: O(n), where n is the length of the word. We traverse the string linearly. |
| Suffix Array Technique | Time Complexity: O(n), covers full traversal of the input word. |
| Dynamic Programming + Prefix Sum | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Dynamic Programming + Prefix Sum | O(m · k) | O(k) | Best general solution when counting valid original lengths with a constraint |
| Suffix Array Technique | O(n log n) | O(n) | Useful when analyzing repetition structure in very large strings |
Frequently asked questions
Is Find the Original Typed String II easy or hard?
Find the Original Typed String II is classified as a Hard problem. The difficulty comes from modeling the long‑press behavior correctly and optimizing the counting process using dynamic programming and prefix sum techniques.
Find the Original Typed String II Python/Java solution
Most implementations use dynamic programming with prefix sums. Python and Java solutions iterate through character groups, update a DP array for possible lengths, and subtract invalid counts from the total combinations. The algorithm runs in O(m · k) time.
How to solve Find the Original Typed String II in O(n)?
A near‑linear approach relies on preprocessing the string structure using advanced string techniques such as suffix arrays or LCP arrays to identify repetition segments quickly. After detecting these segments, combinational counting can be applied to compute valid contractions while enforcing the length constraint.
What is the best approach for Find the Original Typed String II?
Dynamic programming with prefix sum optimization is the most practical solution. Compress the typed string into groups and use DP to count ways to form original lengths below k, then subtract from the total combinations. The approach runs in O(m · k) time where m is the number of character groups.
Is Find the Original Typed String II asked at Google/Amazon/Meta?
Problems involving long‑pressed typing, string compression, and counting combinations with dynamic programming are common in interviews at companies like Google, Amazon, and Meta. Variants of this problem test DP transitions, prefix sums, and string grouping techniques.
What data structure is used in Find the Original Typed String II?
The main solution uses arrays for dynamic programming along with prefix sums to accelerate range updates. The alternative approach relies on suffix arrays and LCP arrays for advanced string analysis.
What is the time complexity of Find the Original Typed String II?
The common optimized solution runs in O(m · k) time and O(k) space. Here m is the number of consecutive character groups in the typed string and k is the minimum required original length constraint.
