
Problem Statement
The task is to investigate if a given searchWord serves as a prefix for any word found in a provided sentence. Each word in the sentence is separated by a single space. If searchWord functions as a prefix for one or more words, return the 1-indexed position of the first word where it appears. Should the searchWord not act as a prefix for any words, return -1. Understanding a "prefix" is crucial here: it refers to any initial section of a string, which in this context allows us to identify whether the characters of searchWord match from the beginning of any word within sentence.
Examples
Example 1
Input:
sentence = "i love eating burger", searchWord = "burg"
Output:
4
Explanation:
"burg" is prefix of "burger" which is the 4th word in the sentence.
Example 2
Input:
sentence = "this problem is an easy problem", searchWord = "pro"
Output:
2
Explanation:
"pro" is prefix of "problem" which is the 2nd and the 6th word in the sentence, but we return 2 as it's the minimal index.
Example 3
Input:
sentence = "i am tired", searchWord = "you"
Output:
-1
Explanation:
"you" is not a prefix of any word in the sentence.
Constraints
1 <= sentence.length <= 1001 <= searchWord.length <= 10sentenceconsists of lowercase English letters and spaces.searchWordconsists of lowercase English letters.
Approach and Intuition
The logic needed to solve this problem can be approached by:
- Split the
sentenceinto individual words using space as a delimiter; this provides a list where each element is a word from the sentence. - Iterate through the list of words, and for each word:
- Check if it starts with the
searchWordusing a string method likestartswith(). - If true, return the current index of that word, adjusted to be 1-indexed (since list indexes in programming languages like Python start at 0, we add one).
- Check if it starts with the
- If the loop completes without finding a match, return
-1indicating that no words in the sentence have the searchWord as a prefix.
The decision to return the index of the first matching word hinges on the potential for multiple words to share the same prefix. By prioritizing the first occurrence, the solution adheres to seeking the "minimum index." Also, it is noteworthy that by employing string manipulation and direct iteration, the solution remains comprehensible and efficient given the problem constraints.
Solutions
- C++
- Java
- Python
class PrefixNode {
public:
unordered_map<char, PrefixNode*> map;
vector<int> positions;
PrefixNode() {}
};
class PrefixTree {
public:
PrefixNode* rootNode;
PrefixTree() { rootNode = new PrefixNode(); }
void insertWord(const string& word, int index) {
PrefixNode* node = rootNode;
for (char letter : word) {
if (node->map.find(letter) == node->map.end()) {
node->map[letter] = new PrefixNode();
}
node = node->map[letter];
node->positions.push_back(index);
}
}
vector<int> searchPrefix(const string& prefix) {
PrefixNode* node = rootNode;
for (char letter : prefix) {
if (node->map.find(letter) == node->map.end()) {
return {};
}
node = node->map[letter];
}
return node->positions;
}
};
class Solution {
public:
int isPrefixOfWord(string sentence, string searchWord) {
PrefixTree prefixTree;
istringstream wordsStream(sentence);
string word;
int wordIndex = 1;
while (wordsStream >> word) {
prefixTree.insertWord(word, wordIndex);
wordIndex++;
}
vector<int> matchedPositions = prefixTree.searchPrefix(searchWord);
return matchedPositions.empty() ? -1 : *min_element(matchedPositions.begin(), matchedPositions.end());
}
};
To check if a word occurs as a prefix of any word in a sentence using C++, implement this solution that utilizes a custom Prefix Tree (Trie). Here's how you can structure your approach:
Define a
PrefixNodeclass:- Create an unordered map to hold child nodes.
- Use a vector to store positions where prefixes end.
Construct the
PrefixTreeclass:- Start with a root
PrefixNode. insertWordfunction: For each word in the sentence, iterate over each character and if the character does not exist as a child of the current node, create a new node. Add the word's index to the positions vector of the last node of each word.searchPrefixfunction: For the given prefix, traverse the tree. If a character from the prefix is not found, return an empty vector. If the traversal is successful, return the vector of word indices stored in the node of the last character of the prefix.
- Start with a root
Define the
Solutionclass and implement theisPrefixOfWordmethod:- Create an instance of
PrefixTree. - Split the input sentence into words and insert each into the prefix tree with its index.
- Search the prefix tree for the given prefix using the
searchPrefixfunction. - If no matches are found, return -1. If matches exist, return the smallest index from the matched positions.
- Create an instance of
This approach efficiently determines if the search word is a prefix for any word in the sentence by leveraging the structured lookup capabilities of a Trie, thus minimizing unnecessary comparisons and optimizing performance, particularly for large datasets or frequent queries.
class TrieNode {
Map<Character, TrieNode> childNodes;
List<Integer> indexList;
public TrieNode() {
childNodes = new HashMap<>();
indexList = new ArrayList<>();
}
}
class Trie {
TrieNode root;
public Trie() {
root = new TrieNode();
}
public void insertWord(String word, int idx) {
TrieNode node = root;
for (char ch : word.toCharArray()) {
if (!node.childNodes.containsKey(ch)) {
node.childNodes.put(ch, new TrieNode());
}
node = node.childNodes.get(ch);
node.indexList.add(idx);
}
}
public List<Integer> searchPrefix(String prefix) {
TrieNode node = root;
for (char ch : prefix.toCharArray()) {
if (!node.childNodes.containsKey(ch)) {
return new ArrayList<>();
}
node = node.childNodes.get(ch);
}
return node.indexList;
}
}
class Solution {
public int isPrefixOfWord(String sentence, String searchPrefix) {
Trie trie = new Trie();
String[] words = sentence.split(" ");
for (int i = 1; i <= words.length; i++) {
trie.insertWord(words[i - 1], i);
}
List<Integer> positions = trie.searchPrefix(searchPrefix);
return positions.isEmpty() ? -1 : Collections.min(positions);
}
}
The provided Java solution determines if a word occurs as a prefix of any word in a given sentence by utilizing a Trie data structure. Here's a breakdown of the solution:
Define a
TrieNodeclass, which includes a hash map for child nodes and a list to store indices of word appearances.Implement a
Trieclass with methods for inserting words and searching for words that start with a specific prefix.The
insertWordmethod takes a word along with its index in the sentence, breaking the word into characters and storing the index at each character node.Utilize the
searchPrefixmethod to move through the Trie based on characters of the prefix. If the prefix is found, the method returns the indices of the words starting with this prefix.The main functionality lies in the
isPrefixOfWordmethod of theSolutionclass. This method:- Splits the sentence into words.
- Inserts each word into the Trie with its respective 1-based index.
- Searches for the minimum index of any word that begins with the given prefix using the Trie and returns it. If no such word exists, it returns -1.
This approach ensures efficient searching and storing of prefixes, making it an optimal solution for checking word occurrences as prefixes in sentences.
class TrieNode:
def __init__(self):
self.children = defaultdict(TrieNode)
self.word_indices = []
class PrefixTrie:
def __init__(self):
self.root = TrieNode()
def insert_word(self, word, index):
node = self.root
for character in word:
node = node.children[character]
node.word_indices.append(index)
def find_prefix(self, prefix):
node = self.root
for character in prefix:
if character not in node.children:
return []
node = node.children[character]
return node.word_indices
class Solution:
def isPrefixOfWord(self, sentence: str, searchWord: str) -> int:
trie = PrefixTrie()
words = sentence.split(" ")
for index, word in enumerate(words, 1):
trie.insert_word(word, index)
indices = trie.find_prefix(searchWord)
return min(indices) if indices else -1
The provided solution determines whether a word appears as a prefix of any word in a given sentence using a Trie data structure in Python. Here's a breakdown of the solution's execution:
Initialization:
- A
TrieNodeclass is established with adefaultdictto dynamically create child nodes and a list,word_indices, to store indices of words where the prefix occurs. - A
PrefixTrieclass contains the root node ofTrieNodeand methods to insert words and find prefixes in the trie.
- A
Insertion of Words:
- Words are inserted into the trie through the
insert_wordmethod. Each word from the sentence, along with its index (1-based), is added to the trie. While inserting, each character of the word is processed—moving deeper into the trie and updating node'sword_indiceswith the current word's index.
- Words are inserted into the trie through the
Prefix Search:
- To determine if a given
searchWordis a prefix, use thefind_prefixmethod. Navigate through the trie by each character of thesearchWord. If a character doesn't lead to any child node in the trie, it means the prefix is not present, and an empty list is returned. - If the traversal of
searchWordcompletes successfully, return the list of indices where the prefix exists.
- To determine if a given
Result Computation:
- The
isPrefixOfWordmethod of theSolutionclass initializes aPrefixTrie, splits the sentence into words, and uses the trie to find ifsearchWordoccurs as a prefix in any of the words. - If the
searchWordis found, it returns the minimum index from the list of indices indicating the earliest position that the prefix appears. Otherwise, it returns -1.
- The
By utilizing a Trie for both insertion and search, this solution efficiently handles the query for prefixes over the list of words in a sentence.