Design a data structure that supports the following two operations:
void addWord(word) bool search(word)
search(word) can search a literal word or a regular expression string containing only letters a-z
or .
. A .
means it can represent any one letter.
For example:
addWord("bad") addWord("dad") addWord("mad") search("pad") -> false search("bad") -> true search(".ad") -> true search("b..") -> true
Note:
You may assume that all words are consist of lowercase letters a-z
.
struct TrieNode {
char c;
bool isLeaf;
TrieNode* child[26];
TrieNode(char cc) : c(cc), isLeaf(false) {
memset(child, NULL, sizeof(child));
}
TrieNode() : isLeaf(false) {
memset(child, NULL, sizeof(child));
}
};
class WordDictionary {
public:
WordDictionary() {
root = new TrieNode();
}
// Adds a word into the data structure.
void addWord(string word) {
if (word.length() == 0)
return;
TrieNode* node = root;
string::iterator it = word.begin();
while (it != word.end())
{
if (node->child[*it - 'a'] == NULL)
node->child[*it - 'a'] = new TrieNode(*it);
node = node->child[*it - 'a'];
++it;
}
node->isLeaf = true;
}
// Returns if the word is in the data structure. A word could
// contain the dot character '.' to represent any one letter.
bool search(string word) {
if (word.length() == 0)
return false;
return searchRecur(word, 0, root);
}
bool searchRecur(string word, int index, TrieNode* node) {
if (index == word.length())
return node->isLeaf;
TrieNode* temp = node;
if (word[index] != '.')
{
temp = node->child[word[index] - 'a'];
if (temp == NULL)
return false;
return searchRecur(word, index + 1, temp);
}
else
{
bool result = false;
for (int i = 0; i < 26; i++)
{
if (node->child[i] != NULL)
{
temp = node->child[i];
result = searchRecur(word, index + 1, temp);
}
if (result)
break;
}
return result;
}
}
private:
TrieNode* root;
};
// Your WordDictionary object will be instantiated and called as such:
// WordDictionary wordDictionary;
// wordDictionary.addWord("word");
// wordDictionary.search("pattern");