Stamping The Sequence⚓︎
Description⚓︎
You are given two strings stamp
and target
. Initially, there is a string s
of length target.length
with all s[i] == '?'
.
In one turn, you can place stamp
over s
and replace every letter in the s
with the corresponding letter from stamp
.
- For example, if
stamp = "abc"
andtarget = "abcba"
, thens
is"?????"
initially. In one turn you can:- place
stamp
at index0
ofs
to obtain"abc??"
, - place
stamp
at index1
ofs
to obtain"?abc?"
, or - place
stamp
at index2
ofs
to obtain"??abc"
.
- place
- Note that
stamp
must be fully contained in the boundaries ofs
in order to stamp (i.e., you cannot placestamp
at index3
ofs
).
We want to convert s
to target
using at most 10 * target.length
turns.
Return an array of the index of the left-most letter being stamped at each turn. If we cannot obtain target
from s
within 10 * target.length
turns, return an empty array.
Example 1:
- Input:
stamp = "abc", target = "ababc"
- Output:
[0,2]
- Explanation:
Example 2:
- Input:
stamp = "abca", target = "aabcaca"
- Output:
[3,0,1]
- Explanation:
Constraints:
1 <= stamp.length <= target.length <= 1000
stamp
andtarget
consist of lowercase English letters.
Solution⚓︎
Topological Sorting⚓︎
See reference (Chinese).
Greedy Solution (Easier to Understand)⚓︎
Time Complexity:
-
Outer Loop (While Loop): This loop runs until no more stamping operations can be performed. In the worst case, this could potentially run \(O(n - m + 1)\) times, where \(n\) is the length of the target string and \(m\) is the length of the stamp string. However, this worst-case scenario is highly unlikely because each successful stamp operation should progressively reduce the number of potential stamping locations. A more realistic upper bound involves considering the number of
'?'
characters introduced per iteration, but exact analysis can be complex due to the greedy nature of the algorithm. For analysis purposes, let's denote the number of iterations in this loop as \(I\). -
Inner Loop (For Loop): The inner loop iterates over every possible starting position for the stamp in the target string, which is \(O(n - m + 1)\).
-
Stamping Check and Operation (
tryStamp
Function): Within this loop, for each position, the stamping operation (including both the check and the actual stamping) takes \(O(m)\) time, where \(m\) is the length of the stamp string.
Combining these, the total time complexity can be approximated as \(O(I \times (n - m + 1) \times m)\). The value of \(I\) depends on the specifics of the input but is bounded by the length of the target string \(n\) in the worst case, leading to a rough upper bound of \(O(n^2 \cdot m)\) when considering highly inefficient stamp placements. However, in practical scenarios, especially with more random or favorable input patterns, \(I\) will be much smaller, and the algorithm will perform significantly better than this worst-case analysis suggests.
Space Complexity:
-
Result Vector (
result
): The space taken by the result vector depends on the number of stamping operations performed, which is at most \(O(n - m + 1)\) in the worst case, as you can't stamp more times than there are positions in the target string for the stamp to fit. -
Temporary Storage: The function uses a constant amount of extra space for variables and does not allocate variable-size data structures proportional to the input size, except for the modifications directly made to the input
target
string, which does not count towards additional space complexity since it is an in-place operation.