You are given two strings s and t consisting of only lowercase English letters.
Return the minimum number of characters that need to be appended to the end of s so that t becomes a subsequence of s.
A subsequence is a string that can be derived from another string by deleting some or no characters without changing the order of the remaining characters.
Example 1:
Input: s = "coaching", t = "coding"
Output: 4Explanation: Append the characters "ding" to the end of s so that s = "coachingding".
Now, t is a subsequence of s (coachingding).
It can be shown that appending any 3 characters to the end of s will never make t a subsequence.
Example 2:
Input: s = "abcde", t = "a"
Output: 0Explanation: t is already a subsequence of s ("abcde").
Example 3:
Input: s = "z", t = "abcde"
Output: 5Explanation: Append the characters "abcde" to the end of s so that s = "zabcde".
Now, t is a subsequence of s (zabcde).
It can be shown that appending any 4 characters to the end of s will never make t a subsequence.
Constraints:
1 <= s.length, t.length <= 100,000s and t consist of lowercase English letters.Before attempting this problem, you should be comfortable with:
To make t a subsequence of s by appending characters, we first need to figure out how much of t is already a subsequence of s. We can greedily match characters from t in s from left to right. Once we know how many characters of t we can match, the remaining characters must be appended.
The greedy approach works because matching earlier characters in s never hurts. If a character from t appears multiple times in s, taking the first occurrence leaves more room for matching subsequent characters.
i for string s and j for string t.s. Whenever s[i] matches t[j], move both pointers forward. Otherwise, only advance i.s, j represents how many characters of t are already matched.len(t) - j, the number of characters that need to be appended to make the match.Where and are the lengths of the strings and , respectively.
The two-pointer approach scans s character by character, which can be slow if s is long and the characters we need are sparse. We can speed this up by precomputing where each character appears in s. For any position, we can instantly jump to the next occurrence of the character we need.
We build a table where store[i][c] tells us the nearest index at or after position i where character c appears. This lets us skip over irrelevant characters in constant time.
store where store[i][c] holds the first occurrence of character c at or after index i in s.s. Each position inherits the next position's data, then updates the current character's entry.i and j for s and t. For each character in t, use store to jump directly to its next occurrence in s.t cannot be found (returns sentinel value), stop matching.len(t) - j.class Solution:
def appendCharacters(self, s: str, t: str) -> int:
n, m = len(s), len(t)
store = [[n + 1] * 26 for _ in range(n)]
store[n - 1][ord(s[n - 1]) - ord('a')] = n - 1
for i in range(n - 2, -1, -1):
store[i] = store[i + 1][:]
store[i][ord(s[i]) - ord('a')] = i
i, j = 0, 0
while i < n and j < m:
if store[i][ord(t[j]) - ord('a')] == n + 1:
break
i = store[i][ord(t[j]) - ord('a')] + 1
j += 1
return m - jWhere and are the lengths of the strings and , respectively.
The result should be the number of unmatched characters in t, not the number of matched characters. After the loop, j represents how many characters were matched, so you need to return len(t) - j, not j.
# Wrong: returning matched count
return j # Returns how many matched, not how many to append
# Correct: return remaining characters
return len(t) - jWhen characters do not match, only the pointer for s should advance. The pointer for t should stay in place waiting for its character to appear later in s. Advancing both pointers skips characters in t that might match later.
# Wrong: advancing both pointers
if s[i] != t[j]:
i += 1
j += 1 # Skips a character in t that might match later
# Correct: only advance s pointer
if s[i] != t[j]:
i += 1