
Problem Statement
In this problem, you are provided with two strings: s and t. The task is to determine whether the string s is a subsequence of the string t. The function should return true if s is a subsequence of t, and false otherwise.
To clarify, a subsequence is derived from another string by deleting some or none of the characters without rearranging the order of the remaining characters. For instance, "ace" is a subsequence of "abcde" because you can remove "b" and "d" from "abcde" to form "ace". However, "aec" is not a subsequence of "abcde" since the letters are not in the same order in both strings.
Examples
Example 1
Input:
s = "abc", t = "ahbgdc"
Output:
true
Example 2
Input:
s = "axc", t = "ahbgdc"
Output:
false
Constraints
0 <= s.length <= 1000 <= t.length <= 104sandtconsist only of lowercase English letters.
Approach and Intuition
To solve the problem of determining if s is a subsequence of t, the key is to check each character of s and ensure it appears in t in the same relative order. If any character in s fails this condition, the function will return false. Below is a step-by-step approach to realize the solution:
- Initialize a
pointerfor stringsat position 0. - Iterate through each character of string
t.- For each character in
t, compare it with the character at the currentpointerposition ofs. - If they match:
- Move the
pointerforward ins(i.e., increment thepointer). - If the
pointerequals the length ofs, it means all characters ofshave been matched intin order, so returntrue.
- Move the
- For each character in
- If the end of
tis reached and there are characters insthat haven't been matched, returnfalse.
This approach ensures a linear time complexity relative to the length of t, making it efficient given the constraint where the length of t can be up to 10,000. Each character of t is processed in sequence, and the process halts early if s is fully matched or continues to the end of t if needed.
Solutions
- Java
- Python
class Solution {
public boolean sequenceMatcher(String str1, String str2) {
Integer len1 = str1.length(), len2 = str2.length();
if (len1 == 0)
return true;
int[][] matchTable = new int[len1 + 1][len2 + 1];
for (int j = 1; j <= len2; ++j) {
for (int i = 1; i <= len1; ++i) {
if (str1.charAt(i - 1) == str2.charAt(j - 1))
matchTable[i][j] = matchTable[i - 1][j - 1] + 1;
else
matchTable[i][j] = Math.max(matchTable[i][j - 1], matchTable[i - 1][j]);
}
if (matchTable[len1][j] == len1)
return true;
}
return false;
}
}
The provided Java solution addresses the problem of determining whether one string (str1) is a subsequence of another string (str2). The method sequenceMatcher accomplishes this by employing a dynamic programming approach using a 2D array, matchTable, to store the lengths of matching subsequences found during the iteration through both strings.
Here's how the solution works:
- Initiate
matchTablewherematchTable[i][j]represents the length of the longest subsequence common tostr1up to i andstr2up to j. - Iterate through each character in
str2(outer loop) and for each character ofstr2, iterate through each character ofstr1(inner loop). - If characters from both strings match, the value in the table is derived from the top-left diagonal cell incremented by one. This indicates the continuation of an existing subsequence.
- If there's no match, the cell's value is the maximum of either the cell directly above or the cell to the left, representing the longest subsequence found so far without including the current character.
- After updating the table through each character of
str2, check if the subsequence having the length ofstr1has been found by looking at the last cell of the current column ofstr2. - If
str1is indeed a subsequence at any point during the traversal ofstr2, return true. - If after completing the traversal, no such subsequence is identified, return false.
This method efficiently determines the relationship between the two strings, optimizing checks and balances through dynamic programming, and provides an immediate exit upon confirmation that a subsequence exists, making it computationally efficient for varying lengths of input strings.
class Solution:
def isSubsequence(self, sub: str, main: str) -> bool:
len_sub, len_main = len(sub), len(main)
if len_sub == 0:
return True
dp_table = [[0] * (len_main + 1) for _ in range(len_sub + 1)]
for i in range(1, len_main + 1):
for j in range(1, len_sub + 1):
if sub[j - 1] == main[i - 1]:
dp_table[j][i] = dp_table[j - 1][i - 1] + 1
else:
dp_table[j][i] = max(dp_table[j][i - 1], dp_table[j - 1][i])
if dp_table[len_sub][i] == len_sub:
return True
return False
The solution provided in Python addresses the problem of checking if one string is a subsequence of another. The function isSubsequence takes two strings, sub and main, and determines if sub is a subsequence within main.
The initial check in the solution handles the case where the subsequence is empty, immediately returning True since an empty sequence is trivially a subsequence of any string.
A dynamic programming approach is used, establishing a 2D list dp_table where dp_table[j][i] will hold the length of longest common subsequence of sub[0:j] and main[0:i].
- A nested loop iterates through both
subandmain.- If characters from
subandmainmatch, the value in the DP table is updated to carry over the length from the previous matched position incremented by one. - If no match occurs, the function carries forward the maximum subsequence length found so far either from skipping a character in
subormain.
- If characters from
The function concludes if the value at dp_table[len_sub][i] is equal to len_sub at any column i, signifying all characters of sub have been matched in sequence within main.
If the end of main is reached and sub has not been fully matched, False is returned. This approach efficiently checks the subsequence condition with the help of dynamic programming, ensuring all possible subsequences of main are explored for a potential complete match with sub.