Difficulty: Easy | Acceptance: 52.80% | Paid: No Topics: Array, Two Pointers, String
Given a string s and an array of strings words, determine whether s is a prefix string of the concatenated string formed by words in order.
A prefix string is a string that can be made by concatenating some prefix of the array words (i.e., some contiguous subarray starting from the beginning).
- Examples
- Constraints
- Approach 1: Iterative Concatenation
- Approach 2: Two Pointers / Index Tracking
Examples
Example 1
Input:
s = "iloveleetcode", words = ["i","love","leetcode","apples"]
Output:
true
Explanation: s can be made by concatenating “i”, “love”, and “leetcode” together.
Example 2
Input:
s = "iloveleetcode", words = ["apples","i","love","leetcode"]
Output:
false
Explanation: It is impossible to make s using a prefix of arr.
Constraints
1 <= words.length <= 100
1 <= words[i].length <= 20
1 <= s.length <= 10⁴
words[i] and s consist of only lowercase English letters.
Approach 1: Iterative Concatenation
Intuition
We can simulate the process of building the prefix string by iterating through the words array and appending each word to a temporary string. After each append, we check if the temporary string matches s or if it has become longer than s.
Steps
- Initialize an empty string
currentto store the concatenated prefix. - Iterate through each word in the
wordsarray. - Append the current word to
current. - Check if
currentis equal tos. If yes, returntrue. - Check if the length of
currentis greater than the length ofs. If yes, returnfalsebecausescannot be a prefix of a string that is already longer than it. - If the loop finishes without finding a match, return
false.
class Solution:
def isPrefixString(self, s: str, words: list[str]) -> bool:
current = ""
for word in words:
current += word
if current == s:
return True
if len(current) > len(s):
return False
return FalseComplexity
- Time: O(N * L), where N is the number of words and L is the average length of a word. In the worst case, we construct a string of length equal to
s. - Space: O(N * L) to store the
currentstring. - Notes: This approach is intuitive but uses extra space to store the concatenated string.
Approach 2: Two Pointers / Index Tracking
Intuition
Instead of building a new string, we can optimize space by tracking the current position (index) in s that we are trying to match. We iterate through the words and then through the characters of each word, comparing them with the corresponding character in s.
Steps
- Initialize a pointer
k = 0to track the current index ins. - Iterate through each word in the
wordsarray. - Iterate through each character in the current word.
- If
kis equal to the length ofs, it means we have successfully matched all characters ofspreviously, but we are still processing a word. This impliessis shorter than the current prefix, so returnfalse. - If the current character from the word does not match
s[k], returnfalse. - Increment
kto move to the next character ins. - After finishing the inner loop (processing a word), check if
kequals the length ofs. If yes, we have matchedsexactly at the end of a word, so returntrue. - If the outer loop finishes, check if
kequals the length ofs(handles the case wheresis empty, though constraints say min length 1) or simply returnfalseif we exited without matching.
class Solution:
def isPrefixString(self, s: str, words: list[str]) -> bool:
k = 0
n = len(s)
for word in words:
for char in word:
if k >= n or char != s[k]:
return False
k += 1
if k == n:
return True
return FalseComplexity
- Time: O(S), where S is the length of
s. We stop iterating as soon as we finish matchingsor find a mismatch. - Space: O(1), as we only use a few integer variables for pointers and do not allocate extra space proportional to the input size.
- Notes: This is the optimal approach as it minimizes space usage and avoids unnecessary string copying.