Welcome to Subscribe On Youtube
3983. Subsequence After One Replacement
Description
You are given two strings s and t consisting of lowercase English letters.
You may choose at most one index in s and replace the character at that index with any lowercase English letter.
Return true if it is possible to make s a subsequence of t; otherwise, return false.
Example 1:
Input: s = "cat", t = "chat"
Output: true
Explanation:
- Replace
s[1]from'a'to'h'. The resulting string is"cht". "cht"is a subsequence of"chat"because we can match'c','h', and't'in order.
Example 2:
Input: s = "plane", t = "apple"
Output: false
Explanation:
- The characters
'p','l', and'e'can be matched int, but the remaining characters cannot be matched while preserving the required order. - Even after replacing any one character in
s, it is impossible to makesa subsequence oft.
Constraints:
1 <= s.length, t.length <= 105sandtconsist only of lowercase English letters.
Solutions
Solution 1: Two Pointers
The problem is equivalent to asking whether we can greedily match $s$ as a subsequence of $t$ while allowing at most one character in $s$ to mismatch, since that character can be replaced with any letter.
We scan $s$ with two pointers $i_0$ and $i_1$, and scan $t$ with pointer $j$:
- $i_0$ is the current position in $s$ when matching without using the replacement.
- $i_1$ is the current position in $s$ when matching with at most one replacement available.
For each character $t[j]$:
- If $s[i_1] = t[j]$, move $i_1$ forward by one.
- Set $i_1 = \max(i_1, i_0 + 1)$ so the replacement position is never before $i_0$, reserving one character for the replacement.
- If $s[i_0] = t[j]$, move $i_0$ forward by one.
- Move $j$ forward by one.
After the scan, if $i_1 = |s|$, then all characters of $s$ can be matched in order within $t$ using at most one replacement, so return true; otherwise return false.
The time complexity is $O(|s| + |t|)$, and the space complexity is $O(1)$.
-
class Solution { public boolean canMakeSubsequence(String s, String t) { int m = s.length(), n = t.length(); int i0 = 0, i1 = 0, j = 0; while (i1 < m && j < n) { if (s.charAt(i1) == t.charAt(j)) { i1++; } i1 = Math.max(i1, i0 + 1); if (s.charAt(i0) == t.charAt(j)) { i0++; } j++; } return i1 == m; } } -
class Solution { public: bool canMakeSubsequence(string s, string t) { int m = s.size(), n = t.size(); int i0 = 0, i1 = 0, j = 0; while (i1 < m && j < n) { if (s[i1] == t[j]) { i1++; } i1 = max(i1, i0 + 1); if (s[i0] == t[j]) { i0++; } j++; } return i1 == m; } }; -
class Solution: def canMakeSubsequence(self, s: str, t: str) -> bool: m, n = len(s), len(t) i0 = i1 = j = 0 while i1 < m and j < n: if s[i1] == t[j]: i1 += 1 i1 = max(i1, i0 + 1) if s[i0] == t[j]: i0 += 1 j += 1 return i1 == m -
func canMakeSubsequence(s string, t string) bool { m, n := len(s), len(t) i0, i1, j := 0, 0, 0 for i1 < m && j < n { if s[i1] == t[j] { i1++ } if i1 < i0+1 { i1 = i0 + 1 } if s[i0] == t[j] { i0++ } j++ } return i1 == m } -
function canMakeSubsequence(s: string, t: string): boolean { const m = s.length, n = t.length; let i0 = 0, i1 = 0, j = 0; while (i1 < m && j < n) { if (s[i1] === t[j]) { i1++; } i1 = Math.max(i1, i0 + 1); if (s[i0] === t[j]) { i0++; } j++; } return i1 === m; }