Check If String Is a Prefix of Array
EasyPrompt
Given a string s and an array of strings words, determine whether s is a prefix string of words.
A string s is a prefix string of words if s can be made by concatenating the first k strings in words for some positive k no larger than words.length.
Return true if s is a prefix string of words, or false otherwise.
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 <= 1001 <= words[i].length <= 201 <= s.length <= 1000words[i]andsconsist of only lowercase English letters.
Approaches
2 approaches with complexity analysis and trade-offs.
This approach involves building a prefix string by concatenating words from the words array one by one. After each concatenation, we compare the resulting string with the target string s. This is an intuitive way to solve the problem as it directly simulates the process described in the problem statement.
Algorithm
- Initialize an empty
StringBuildercalledprefixBuilder. - Iterate through each
wordin thewordsarray. - Append the current
wordtoprefixBuilder. - After appending, check if the length of
prefixBuilderhas exceeded the length ofs. If so, it's impossible to forms, so we can immediately returnfalse. - Convert
prefixBuilderto a string and compare it withs. - If they are equal, it means
sis a prefix string ofwords. Returntrue. - If the loop completes without finding a match, it means no prefix of
wordsconcatenates tos. Returnfalse.
Walkthrough
We use a StringBuilder for efficient string concatenation. We iterate through the words array, appending each word to our StringBuilder. In each step of the iteration, we check two conditions:
- If the length of our constructed string exceeds the length of
s, it's impossible for it to be a prefix string, so we can stop and returnfalse. - If the constructed string is exactly equal to
s, we have found a match, and we can returntrue.
If we iterate through all the words and the constructed string never equals s, it means s is not a prefix string of words, so we return false.
class Solution { public boolean isPrefixString(String s, String[] words) { StringBuilder prefixBuilder = new StringBuilder(); for (String word : words) { prefixBuilder.append(word); if (prefixBuilder.toString().equals(s)) { return true; } if (prefixBuilder.length() > s.length()) { return false; } } return false; }}Complexity
Time
O(N * M), where N is the number of words and M is the length of `s`. In the worst case, for each of the `k` words that form a prefix, we create and compare a string of increasing length. The total work can be approximated as the sum of lengths of prefixes, which can be up to O(k * M). Since k can be at most N, the complexity is O(N * M).
Space
O(M), where M is the length of the string `s`. The `StringBuilder` will store characters up to a length comparable to `s`.
Trade-offs
Pros
Intuitive and easy to understand.
Directly models the process described in the problem statement.
Cons
Less efficient in terms of time complexity due to repeated string creation (
toString()) and comparisons within the loop.Uses more memory to build the intermediate string.
A more efficient approach avoids building an intermediate string altogether. Instead, we can treat the words array as a single logical stream of characters and compare it directly with s using a pointer or an index. This avoids the overhead of creating new string objects in a loop.
Algorithm
- Initialize an integer
sIndex = 0to keep track of the matched portion ofs. - Iterate through each
wordin thewordsarray. - For each
word, check ifsstarts with thiswordat the currentsIndex. Thes.startsWith(word, sIndex)method is ideal for this. - If it does not match,
scannot be formed. Returnfalse. - If it does match, advance the
sIndexby the length of theword. - After advancing the index, check if
sIndexis now equal to the length ofs. If it is, we have successfully constructeds. Returntrue. - If the loop finishes but we haven't returned
true, it means the concatenated words from the array are a prefix ofsbut not equal tos. Returnfalse.
Walkthrough
We maintain an index, sIndex, that tracks our current position in the target string s. We iterate through the words array. For each word, we check if the substring of s starting from sIndex matches the word. If at any point there is a mismatch, or if we exhaust the words before fully matching s, we know it's not a valid prefix string. If we perfectly match s after processing some k-th word, we've found our answer.
class Solution { public boolean isPrefixString(String s, String[] words) { int sIndex = 0; for (String word : words) { // Check if we've already matched s or if the next word doesn't fit. if (sIndex >= s.length() || !s.startsWith(word, sIndex)) { return false; } // Move the index forward. sIndex += word.length(); // If we have matched the entire string s, we are done. if (sIndex == s.length()) { return true; } } // The loop finished, but s was not fully matched. return false; }}Complexity
Time
O(M), where M is the length of the string `s`. The `startsWith` check compares characters of `word` with characters of `s`. Each character of `s` is visited at most once across all calls. Therefore, the total time is proportional to the number of characters we successfully match, which is at most `M`.
Space
O(1). We only use a few variables to keep track of the index, requiring constant extra space.
Trade-offs
Pros
Highly efficient in both time and space.
Avoids creating new string objects in a loop, which is a common performance bottleneck.
Processes each character of the target string
sat most once.
Cons
May be slightly less direct to read for a beginner compared to the concatenation approach, though it's a standard pattern for string problems.
Solutions
Solution
class Solution {public boolean isPrefixString(String s, String[] words) { StringBuilder t = new StringBuilder(); for (var w : words) { t.append(w); if (t.length() > s.length()) { return false; } if (t.length() == s.length()) { return s.equals(t.toString()); } } return false; }}class Solution {public: bool isPrefixString(string s, vector<string> &words) { string t; for (auto &w : words) { t += w; if (t.size() > s.size()) { return false; } if (t.size() == s.size()) { return t == s; } } return false; }};class Solution : def isPrefixString ( self , s : str , words : List [ str ]) -> bool : n , m = len ( s ), 0 for i , w in enumerate ( words ): m += len ( w ) if m == n : return "" . join ( words [: i + 1 ]) == s return FalseVideo walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.