466. Count The Repetitions
Problem Description
This problem asks you to find how many times a repeated string can be obtained from another repeated string through character removal.
First, let's understand the notation [s, n]
which means string s
repeated n
times. For example, ["abc", 3]
gives us "abcabcabc"
.
The problem defines that string s1
can be "obtained from" string s2
if we can remove some characters from s2
to get s1
. For instance, "abc"
can be obtained from "ab**dbe**c"
by removing the characters 'd', 'b', and 'e'.
Given:
- Two strings
s1
ands2
- Two integers
n1
andn2
- This creates
str1 = [s1, n1]
(strings1
repeatedn1
times) - And
str2 = [s2, n2]
(strings2
repeatedn2
times)
The task is to find the maximum integer m
such that [str2, m]
(which means str2
repeated m
times) can be obtained from str1
.
In other words, you need to determine how many complete copies of str2
can be formed by removing characters from str1
, where both str1
and str2
are themselves repeated strings.
For example, if s1 = "acb"
, n1 = 4
, s2 = "ab"
, n2 = 2
:
str1 = "acbacbacbacb"
(repeating "acb" 4 times)str2 = "abab"
(repeating "ab" 2 times)- From
str1
, we can obtain multiple copies ofstr2
by removing appropriate characters - The answer would be the maximum number of times
str2
can be obtained fromstr1
Intuition
The key insight is that when we're matching characters from s1
to form s2
, there's a repeating pattern that emerges. Since we're dealing with repeated strings, after processing one complete s1
, we'll be at some position in s2
. This position and the number of complete s2
strings we've formed create a cycle.
Think about it this way: when we scan through one complete s1
, we're essentially asking "starting from position i
in s2
, how many complete s2
strings can I form, and where will I end up in s2
?" Since s2
has a finite length, there are only a limited number of starting positions (0 to len(s2)-1
).
The brilliant observation is that we can precompute this information for all possible starting positions in s2
. For each starting position i
in s2
, we can determine:
- How many complete
s2
strings we can form by going through ones1
(let's call thiscnt
) - What position in
s2
we'll be at after processing ones1
(let's call thisj
)
This creates a mapping: d[i] = (cnt, j)
. This tells us that if we start at position i
in s2
and process one complete s1
, we'll form cnt
complete s2
strings and end up at position j
in s2
.
Once we have this mapping, simulating the entire process becomes straightforward. We just need to iterate n1
times (for each repetition of s1
), and for each iteration, we look up our current position in the precomputed table to find how many s2
strings we formed and where we'll be next.
The final step is dividing by n2
because we're looking for complete str2
strings (which is s2
repeated n2
times), not just complete s2
strings.
This approach transforms what could be a character-by-character simulation of potentially very long strings into a simple iteration with precomputed state transitions.
Solution Approach
The implementation follows a two-phase approach: preprocessing and iteration.
Phase 1: Preprocessing
We create a dictionary d
to store the state transitions. For each possible starting position i
in s2
(where i
ranges from 0 to len(s2)-1
), we simulate matching one complete s1
:
for i in range(n): # n is the length of s2
cnt = 0 # count of complete s2 strings formed
j = i # current position in s2
for c in s1:
if c == s2[j]:
j += 1
if j == n: # reached the end of s2
cnt += 1
j = 0 # wrap around to start of s2
d[i] = (cnt, j)
For each starting position i
, we:
- Initialize a counter
cnt
to track completes2
strings formed - Set current position
j
toi
- Iterate through each character
c
ins1
:- If
c
matches the current character ins2
at positionj
, advancej
- If we've completed
s2
(whenj == n
), incrementcnt
and resetj
to 0
- If
- Store the result as
d[i] = (cnt, j)
, wherecnt
is the number of completes2
strings andj
is the final position ins2
Phase 2: Iteration
Now we simulate processing n1
copies of s1
:
ans = 0
j = 0 # start at position 0 in s2
for _ in range(n1):
cnt, j = d[j] # lookup precomputed values
ans += cnt # add complete s2 strings formed
We:
- Start with position
j = 0
ins2
- For each of the
n1
repetitions ofs1
:- Look up
d[j]
to get the number of completes2
strings and the next position - Add
cnt
to our running total - Update
j
to the new position for the next iteration
- Look up
Final Calculation
Since we want complete str2
strings (where str2 = [s2, n2]
), we divide the total count of s2
strings by n2
:
return ans // n2
This approach has a time complexity of O(|s2| × |s1| + n1)
where the first term is for preprocessing and the second for iteration. The space complexity is O(|s2|)
for storing the transition table.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example with s1 = "acb"
, n1 = 4
, s2 = "ab"
, n2 = 2
.
First, we need to understand what we're looking for:
str1 = "acbacbacbacb"
(repeating "acb" 4 times)str2 = "abab"
(repeating "ab" 2 times)- We want to find how many complete
str2
strings can be obtained fromstr1
Phase 1: Build the transition table
We'll create a dictionary d
where d[i]
tells us what happens when we start at position i
in s2
and process one complete s1
.
For s2 = "ab"
, we have positions 0 and 1:
Starting at position 0 in s2:
- We need to match 'a' (at position 0 in s2)
- Process s1 = "acb":
- 'a' matches s2[0='a'] → advance to position 1
- 'c' doesn't match s2[1='b'] → stay at position 1
- 'b' matches s2[1='b'] → advance to position 2 (which wraps to 0), we completed one s2!
- Result:
d[0] = (1, 0)
(completed 1 copy of s2, ended at position 0)
Starting at position 1 in s2:
- We need to match 'b' (at position 1 in s2)
- Process s1 = "acb":
- 'a' doesn't match s2[1='b'] → stay at position 1
- 'c' doesn't match s2[1='b'] → stay at position 1
- 'b' matches s2[1='b'] → advance to position 2 (which wraps to 0), we completed one s2!
- Result:
d[1] = (1, 0)
(completed 1 copy of s2, ended at position 0)
Phase 2: Simulate n1 iterations
Now we process 4 copies of s1, starting at position 0 in s2:
- Iteration 1: Start at position 0 →
d[0] = (1, 0)
→ gained 1 s2, now at position 0 - Iteration 2: Start at position 0 →
d[0] = (1, 0)
→ gained 1 s2, now at position 0 - Iteration 3: Start at position 0 →
d[0] = (1, 0)
→ gained 1 s2, now at position 0 - Iteration 4: Start at position 0 →
d[0] = (1, 0)
→ gained 1 s2, now at position 0
Total s2 strings formed: 1 + 1 + 1 + 1 = 4
Final Calculation
We formed 4 complete s2 strings. Since str2 = [s2, 2] (meaning 2 copies of s2), we have:
- Number of complete str2 strings = 4 // 2 = 2
Therefore, the answer is 2. We can obtain str2 = "abab" exactly 2 times from str1 = "acbacbacbacb".
To verify: From "acbacbacbacb", we can extract:
- First "abab": acbacbacbacb
- Second "abab": acbacbacbacb
Solution Implementation
1class Solution:
2 def getMaxRepetitions(self, s1: str, n1: int, s2: str, n2: int) -> int:
3 """
4 Find the maximum number of times str2 = s2 * n2 can be obtained from str1 = s1 * n1.
5
6 Args:
7 s1: The base string to be repeated n1 times
8 n1: Number of times s1 is repeated
9 s2: The pattern string to be repeated n2 times
10 n2: Number of times s2 is repeated
11
12 Returns:
13 Maximum number of str2 that can be obtained from str1
14 """
15 s2_length = len(s2)
16
17 # Build a transition table for each starting position in s2
18 # Key: starting index in s2
19 # Value: (number of complete s2 cycles, ending index in s2) after processing one s1
20 transition_table = {}
21
22 for start_index in range(s2_length):
23 complete_cycles = 0
24 current_index = start_index
25
26 # Process one complete s1 string
27 for char in s1:
28 if char == s2[current_index]:
29 current_index += 1
30
31 # Check if we completed one cycle of s2
32 if current_index == s2_length:
33 complete_cycles += 1
34 current_index = 0
35
36 transition_table[start_index] = (complete_cycles, current_index)
37
38 # Simulate processing n1 copies of s1
39 total_s2_cycles = 0
40 current_s2_index = 0
41
42 for _ in range(n1):
43 # Get transition result from current position
44 cycles_gained, next_index = transition_table[current_s2_index]
45 total_s2_cycles += cycles_gained
46 current_s2_index = next_index
47
48 # Calculate how many complete str2 (s2 * n2) we can form
49 return total_s2_cycles // n2
50
1class Solution {
2 public int getMaxRepetitions(String s1, int n1, String s2, int n2) {
3 int s1Length = s1.length();
4 int s2Length = s2.length();
5
6 // dp[i] stores [count, nextIndex] where:
7 // - count: number of complete s2 strings we can match when starting from index i in s2
8 // - nextIndex: the index in s2 where we end up after processing one complete s1
9 int[][] dp = new int[s2Length][2];
10
11 // Precompute the transition for each possible starting position in s2
12 for (int startIndex = 0; startIndex < s2Length; startIndex++) {
13 int currentS2Index = startIndex;
14 int completeS2Count = 0;
15
16 // Process one complete s1 string
17 for (int s1Index = 0; s1Index < s1Length; s1Index++) {
18 // If characters match, advance the pointer in s2
19 if (s1.charAt(s1Index) == s2.charAt(currentS2Index)) {
20 currentS2Index++;
21
22 // If we completed one full s2, reset index and increment count
23 if (currentS2Index == s2Length) {
24 currentS2Index = 0;
25 completeS2Count++;
26 }
27 }
28 }
29
30 // Store the result: [number of complete s2 found, ending position in s2]
31 dp[startIndex] = new int[] {completeS2Count, currentS2Index};
32 }
33
34 // Calculate total number of s2 strings we can obtain from n1 copies of s1
35 int totalS2Count = 0;
36 int currentS2Position = 0;
37
38 // Process each copy of s1
39 for (int remaining = n1; remaining > 0; remaining--) {
40 // Add the number of complete s2 strings from current position
41 totalS2Count += dp[currentS2Position][0];
42 // Update position for next iteration
43 currentS2Position = dp[currentS2Position][1];
44 }
45
46 // Return how many complete (s2 * n2) sequences we can form
47 return totalS2Count / n2;
48 }
49}
50
1class Solution {
2public:
3 int getMaxRepetitions(string s1, int n1, string s2, int n2) {
4 int len1 = s1.size();
5 int len2 = s2.size();
6
7 // For each starting position in s2, precompute:
8 // - How many complete s2 sequences we can match using one s1
9 // - The ending position in s2 after matching through one s1
10 vector<pair<int, int>> transitions;
11
12 for (int startPos = 0; startPos < len2; ++startPos) {
13 int currentPos = startPos;
14 int completeMatches = 0;
15
16 // Simulate matching through one complete s1
17 for (int i = 0; i < len1; ++i) {
18 if (s1[i] == s2[currentPos]) {
19 currentPos++;
20 // If we completed one s2 sequence
21 if (currentPos == len2) {
22 completeMatches++;
23 currentPos = 0; // Reset to beginning of s2
24 }
25 }
26 }
27
28 // Store the number of complete s2 matches and ending position
29 transitions.emplace_back(completeMatches, currentPos);
30 }
31
32 // Count total s2 sequences matched across all n1 copies of s1
33 int totalS2Matches = 0;
34 int currentS2Position = 0; // Starting position in s2
35
36 for (int iteration = 0; iteration < n1; ++iteration) {
37 // Add matches from this s1 copy based on current s2 position
38 totalS2Matches += transitions[currentS2Position].first;
39 // Update position for next s1 copy
40 currentS2Position = transitions[currentS2Position].second;
41 }
42
43 // Return how many complete [s2, n2] we can form
44 return totalS2Matches / n2;
45 }
46};
47
1/**
2 * Calculates the maximum number of times s2 can be obtained from s1
3 * where s1 is repeated n1 times and s2 is repeated n2 times
4 * @param s1 - The first string
5 * @param n1 - Number of times s1 is repeated
6 * @param s2 - The second string
7 * @param n2 - Number of times s2 is repeated
8 * @returns Maximum repetitions of s2*n2 that can be obtained from s1*n1
9 */
10function getMaxRepetitions(s1: string, n1: number, s2: string, n2: number): number {
11 const s2Length: number = s2.length;
12
13 // Create a 2D array to store state transitions
14 // transitions[i][0]: number of complete s2 strings found when starting from index i of s2
15 // transitions[i][1]: ending position in s2 after processing one complete s1
16 const transitions: number[][] = Array.from(
17 { length: s2Length },
18 () => [0, 0]
19 );
20
21 // Precompute transitions for each starting position in s2
22 for (let startIndex: number = 0; startIndex < s2Length; startIndex++) {
23 let currentIndex: number = startIndex;
24 let completeS2Count: number = 0;
25
26 // Process one complete s1 string
27 for (const char of s1) {
28 if (char === s2[currentIndex]) {
29 currentIndex++;
30
31 // If we've matched all of s2, reset and increment count
32 if (currentIndex === s2Length) {
33 currentIndex = 0;
34 completeS2Count++;
35 }
36 }
37 }
38
39 // Store the transition result
40 transitions[startIndex] = [completeS2Count, currentIndex];
41 }
42
43 // Calculate total s2 strings found using the transition table
44 let totalS2Count: number = 0;
45 let currentS2Index: number = 0;
46
47 // Process n1 repetitions of s1
48 while (n1 > 0) {
49 totalS2Count += transitions[currentS2Index][0];
50 currentS2Index = transitions[currentS2Index][1];
51 n1--;
52 }
53
54 // Return the number of complete s2*n2 sequences
55 return Math.floor(totalS2Count / n2);
56}
57
Time and Space Complexity
Time Complexity: O(m × n + n₁)
The algorithm consists of two main parts:
-
Preprocessing phase: Building the dictionary
d
by iterating through alln
possible starting positions ins2
. For each starting positioni
(wherei
ranges from0
ton-1
), we iterate through all characters ins1
(lengthm
) to count how many completes2
sequences can be formed. This gives usO(m × n)
time complexity for the preprocessing. -
Simulation phase: We then iterate
n1
times to simulate going throughs1
forn1
repetitions. In each iteration, we perform a constant-time lookup in the dictionaryd
to get the precomputed values(cnt, j)
. This phase takesO(n₁)
time.
Therefore, the total time complexity is O(m × n + n₁)
, where m = len(s1)
, n = len(s2)
, and n₁
is the repetition count for s1
.
Space Complexity: O(n)
The algorithm uses a dictionary d
to store precomputed values for each possible starting position in s2
. Since there are exactly n
possible starting positions (indices 0
to n-1
), and each entry stores a tuple of two integers (cnt, j)
, the space complexity is O(n)
, where n = len(s2)
.
Common Pitfalls
1. Not Handling Empty or Invalid Input
The code assumes both s1
and s2
contain valid characters and are non-empty. If s2
is empty or n1
/n2
are zero, the code will fail with division by zero or other errors.
Solution:
def getMaxRepetitions(self, s1: str, n1: int, s2: str, n2: int) -> int:
# Add input validation
if not s1 or not s2 or n1 == 0 or n2 == 0:
return 0
# Check if s1 contains all characters needed for s2
if not all(c in s1 for c in set(s2)):
return 0
# Rest of the implementation...
2. Cycle Detection Optimization Missed
The current solution simulates all n1
iterations linearly, which can be inefficient when n1
is very large. Since the state transitions form a cycle, we could detect and skip the cycle.
Solution:
def getMaxRepetitions(self, s1: str, n1: int, s2: str, n2: int) -> int:
s2_length = len(s2)
transition_table = {}
# Build transition table (same as before)
for start_index in range(s2_length):
# ... (preprocessing code)
transition_table[start_index] = (complete_cycles, current_index)
# Detect cycle using Floyd's algorithm or state tracking
visited = {}
total_s2_cycles = 0
current_s2_index = 0
for iteration in range(n1):
if current_s2_index in visited:
# Cycle detected
cycle_start = visited[current_s2_index][0]
cycle_length = iteration - cycle_start
cycles_in_cycle = total_s2_cycles - visited[current_s2_index][1]
# Calculate remaining iterations
remaining = n1 - iteration
full_cycles = remaining // cycle_length
remainder = remaining % cycle_length
# Add cycles from full repetitions
total_s2_cycles += full_cycles * cycles_in_cycle
# Process remainder
for _ in range(remainder):
cycles_gained, current_s2_index = transition_table[current_s2_index]
total_s2_cycles += cycles_gained
return total_s2_cycles // n2
visited[current_s2_index] = (iteration, total_s2_cycles)
cycles_gained, current_s2_index = transition_table[current_s2_index]
total_s2_cycles += cycles_gained
return total_s2_cycles // n2
3. Integer Overflow for Large Values
When n1
is very large (up to 10^6), the multiplication and accumulation of cycles could potentially cause issues in languages with fixed integer sizes (though Python handles arbitrary precision integers).
Solution:
Early termination when we know we can't form any more complete str2
:
def getMaxRepetitions(self, s1: str, n1: int, s2: str, n2: int) -> int:
# ... (previous code)
# During simulation
for iteration in range(n1):
cycles_gained, current_s2_index = transition_table[current_s2_index]
total_s2_cycles += cycles_gained
# Early termination: if no progress is possible
if cycles_gained == 0 and current_s2_index == 0:
# We've completed a full cycle without any matches
break
return total_s2_cycles // n2
Which two pointer techniques do you use to check if a string is a palindrome?
Recommended Readings
What is Dynamic Programming Prerequisite DFS problems dfs_intro Backtracking problems backtracking Memoization problems memoization_intro Pruning problems backtracking_pruning Dynamic programming is an algorithmic optimization technique that breaks down a complicated problem into smaller overlapping sub problems in a recursive manner and uses solutions to the sub problems to construct a solution
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Don’t Miss This!