Coding questions · Pinterest
Fewest Subsequences of a Source String That Concatenate to a Target String
Given a source string and a target string, return the fewest subsequences of the source whose concatenation equals the target, or -1 when the target cannot be formed. It tests subsequence matching, greedy reasoning about why a choice is optimal, and an efficient iterative implementation.
You are given two strings, source and target. A subsequence of source is any string obtained by deleting zero or more characters of source without changing the order of the characters that remain.
Return the minimum number of subsequences of source that, concatenated in order, form exactly target. If target cannot be formed this way, return -1.
In the reported screen this came in two stages: first decide only whether target can be formed at all, then compute the minimum number of subsequences. The function below answers both, with -1 meaning that it cannot be formed.
Function Signature
def min_subsequences_to_form(source: str, target: str) -> int:
Rules
- The same subsequence of
sourcemay be used any number of times, and each use counts separately. - Every subsequence used must be non-empty.
- Characters are matched exactly.
Constraints
1 <= len(source) <= 10001 <= len(target) <= 1000sourceandtargetcontain only lowercase English lettersatoz.- The result is either
-1or an integer from1tolen(target)inclusive, and it is uniquely determined by the input.
Examples
Example 1
- Input:
source = "cab",target = "abcab" - Output:
2 - Explanation:
"ab"and"cab"are both subsequences of"cab", and"ab" + "cab" = "abcab". One subsequence is not enough, becausetargetis longer thansource.
Example 2
- Input:
source = "abc",target = "abd" - Output:
-1 - Explanation:
ddoes not occur insource, so no concatenation of its subsequences can contain it.
Example 3
- Input:
source = "xyz",target = "zyxz" - Output:
3 - Explanation: One optimal split is
"z" + "y" + "xz". Two pieces are impossible: insource,zcomes afteryandycomes afterx, so no subsequence contains"zy"or"yx", and each ofz,yand the followingxmust therefore start a new piece.
Fewest Source Subsequences to Build a Target
You are given two strings, source and target. A subsequence of source is any string obtained by deleting zero or more characters of source without changing the relative order of the characters that remain.
Return the minimum number of subsequences of source that, concatenated in order, form exactly target. If target cannot be formed this way, return -1.
This screen was asked in two stages: first decide only whether target can be formed at all, then compute the minimum number of pieces. Your function answers both at once: -1 means it cannot be formed, and any other value is the minimum count.
Rules:
- The same subsequence of
sourcemay be used any number of times; each use counts separately. - Every subsequence used must be non-empty.
- Characters are matched exactly.
The answer is a single integer that is uniquely determined by the input: either -1, or an integer from 1 to len(target) inclusive.
Constraints:
1 <= len(source) <= 10001 <= len(target) <= 1000sourceandtargetcontain only lowercase English lettersatoz.
Example 1
Input: source = "cab", target = "abcab"
Output: 2
"ab" and "cab" are both subsequences of "cab", and "ab" + "cab" = "abcab". One piece is not enough because target is longer than source.
Example 2
Input: source = "abc", target = "abd"
Output: -1
d never occurs in source, so no concatenation of its subsequences can contain it.
Example 3
Input: source = "xyz", target = "zyxz"
Output: 3
One optimal split is "z" + "y" + "xz". Two pieces are impossible: in source, z comes after y and y comes after x, so no subsequence contains "zy" or "yx".
Hints
- If some letter of target never appears in source, no number of pieces can help. Otherwise, is the answer always finite?
- When building one piece, is it ever worse to match each target character at the earliest possible position in source that is still available?
- Precompute, for every index i of source and every letter, the next index at or after i where that letter occurs, so each target character is handled in O(1).
Approach
Greedy pass-by-pass matching is optimal. Build each piece by scanning source from left to right and matching the next character of target at the earliest position still available; when the current pass cannot absorb the next target character, close the piece and start a new pass from the beginning of source.
Why greedy is optimal: consider any optimal split. By an exchange argument, extending the first piece as far as possible never hurts: if the greedy first piece covers target[0:g] and an optimal first piece covers target[0:k] with k <= g, the remaining suffix target[g:] is a suffix of target[k:], and a suffix of a string formed by p pieces can be formed by at most p pieces (drop or trim the leading ones; trimming a subsequence from the front still leaves a subsequence). Induction over pieces gives that greedy uses no more pieces than optimal. Matching each character at the earliest available position is what lets a single pass absorb the longest possible prefix.
Feasibility: if every letter of target occurs somewhere in source, each character alone is a valid one-letter piece, so the answer is at most len(target). If some letter is missing, return -1.
Implementation: nxt[i][c] stores the smallest index j >= i with source[j] equal to letter c (or n when none), computed right to left in O(26 * n). Walking target keeps pos, the next usable source index for the current piece. If nxt[0][c] == n the letter is absent and the answer is -1; if nxt[pos][c] == n the current pass is exhausted, so the count increments and pos resets to 0; then pos = nxt[pos][c] + 1.
- Time complexity: O(26 * n + m), where n = len(source) and m = len(target)
- Space complexity: O(26 * n)