Design a data structure that supports adding new words and finding if a string matches any previously added string.
Implement the WordDictionary class:
Input:
[“WordDictionary”,“addWord”,“addWord”,“addWord”,“search”,“search”,“search”,“search”]
[[],[“bad”],[“dad”],[“mad”],[“pad”],[“bad”],[“.ad”],[“b…”]]
Output:
[null,null,null,null,false,true,true,true]
Explanation:
WordDictionary wordDictionary = new WordDictionary();
wordDictionary.addWord(“bad”);
wordDictionary.addWord(“dad”);
wordDictionary.addWord(“mad”);
wordDictionary.search(“pad”); // return False
wordDictionary.search(“bad”); // return True
wordDictionary.search(“.ad”); // return True
wordDictionary.search(“b…”); // return True
From: LeetCode
Link: 211. Design Add and Search Words Data Structure
1. TrieNode Structure:
Each node in the Trie is represented by a TrieNode structure. It has the following components:
2. WordDictionary Structure:
The WordDictionary itself is represented by a structure, which holds a pointer to the root node of the Trie.
3. wordDictionaryCreate:
This function initializes the WordDictionary object and allocates memory for the root node of the Trie.
4. wordDictionaryAddWord:
This function is used to insert words into the Trie. For each character in the word, it traverses down the Trie, creating new nodes if needed, until the end of the word is reached, at which point it sets the isEndOfWord flag to true.
5. wordDictionarySearch and searchHelper:
6. wordDictionaryFree and freeNode:
#define ALPHABET_SIZE 26
typedef struct TrieNode {
struct TrieNode *children[ALPHABET_SIZE];
bool isEndOfWord;
} TrieNode;
typedef struct {
TrieNode *root;
} WordDictionary;
TrieNode* createNode() {
TrieNode *newNode = (TrieNode *)calloc(1, sizeof(TrieNode));
return newNode;
}
WordDictionary* wordDictionaryCreate() {
WordDictionary *dict = (WordDictionary *)malloc(sizeof(WordDictionary));
dict->root = createNode();
return dict;
}
void wordDictionaryAddWord(WordDictionary* obj, char * word) {
TrieNode *node = obj->root;
for (int i = 0; word[i] != '\0'; i++) {
int index = word[i] - 'a';
if (!node->children[index])
node->children[index] = createNode();
node = node->children[index];
}
node->isEndOfWord = true;
}
bool searchHelper(TrieNode *node, char *word) {
for (int i = 0; word[i] != '\0'; i++) {
if (word[i] == '.') {
for (int j = 0; j < ALPHABET_SIZE; j++) {
if (node->children[j] && searchHelper(node->children[j], word + i + 1))
return true;
}
return false;
} else {
int index = word[i] - 'a';
if (!node->children[index])
return false;
node = node->children[index];
}
}
return node->isEndOfWord;
}
bool wordDictionarySearch(WordDictionary* obj, char * word) {
return searchHelper(obj->root, word);
}
void freeNode(TrieNode *node) {
for(int i = 0; i < ALPHABET_SIZE; i++)
if(node->children[i])
freeNode(node->children[i]);
free(node);
}
void wordDictionaryFree(WordDictionary* obj) {
if(!obj) return;
freeNode(obj->root);
free(obj);
}
/**
* Your WordDictionary struct will be instantiated and called as such:
* WordDictionary* obj = wordDictionaryCreate();
* wordDictionaryAddWord(obj, word);
* bool param_2 = wordDictionarySearch(obj, word);
* wordDictionaryFree(obj);
*/