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 lettersa-z
or.
. A.
means it can represent any one letter.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 consist of lowercase letters a - z.
Here is my solution to this challenge:
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace TrieQuestions
{
/// <summary>
/// https://leetcode.com/explore/learn/card/trie/148/practical-application-i/1052/
/// </summary>
[TestClass]
public class WordDictionaryTest
{
[TestMethod]
public void AddWordTest()
{
WordDictionary wordDic = new WordDictionary();
wordDic.AddWord("cat");
Assert.IsTrue(wordDic.Search("cat"));
}
[TestMethod]
public void SearchWordDoT()
{
WordDictionary wordDic = new WordDictionary();
wordDic.AddWord("cat");
Assert.IsTrue(wordDic.Search("c.t"));
}
[TestMethod]
public void SearchWordOne()
{
WordDictionary wordDic = new WordDictionary();
wordDic.AddWord("a");
Assert.IsTrue(wordDic.Search("."));
}
[TestMethod]
public void LeetCodeTest()
{
WordDictionary wordDic = new WordDictionary();
wordDic.AddWord("bad");
wordDic.AddWord("dad");
wordDic.AddWord("mad");
Assert.IsFalse(wordDic.Search("pad"));
Assert.IsTrue(wordDic.Search("bad"));
Assert.IsTrue(wordDic.Search(".ad"));
Assert.IsTrue(wordDic.Search("b.."));
}
[TestMethod]
public void LeetCodeTest2()
{
WordDictionary wordDic = new WordDictionary();
wordDic.AddWord("at");
wordDic.AddWord("and");
wordDic.AddWord("an");
wordDic.AddWord("add");
Assert.IsFalse(wordDic.Search("a"));
Assert.IsFalse(wordDic.Search(".at"));
wordDic.AddWord("bat");
Assert.IsTrue(wordDic.Search(".at"));
Assert.IsTrue(wordDic.Search("an."));
Assert.IsFalse(wordDic.Search("a.d."));
Assert.IsFalse(wordDic.Search("b."));
Assert.IsTrue(wordDic.Search("a.d"));
Assert.IsFalse(wordDic.Search("."));
}
}
public class WordDictionary
{
private TrieNode _head;
/** Initialize your data structure here. */
public WordDictionary()
{
_head = new TrieNode();
}
/** Adds a word into the data structure. */
public void AddWord(string word)
{
var current = _head;
foreach (var letter in word)
{
if (!current.Edges.TryGetValue(letter, out var output))
{
output = current.Edges[letter] = new TrieNode();
}
current = output;
}
current.IsTerminal = true;
}
/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
public bool Search(string word)
{
return Match(word, 0, _head);
}
private bool Match(string word, int i, TrieNode node)
{
if (i == word.Length)
{
return node.IsTerminal;
}
//if this is a regular letter check if it exists and mode on to the next letter
if (word[i] != '.')
{
if (!node.Edges.ContainsKey(word[i]))
{
return false;
}
else
{
return Match(word, i + 1, node.Edges[word[i]]);
}
}
else
{
//if we get a . try all of the different letters in recursion
// if one of them returns true return true, there is a valid path to the next letter
foreach (var currentNode in node.Edges)
{
if (Match(word, i + 1, currentNode.Value))
{
return true;
}
}
}
return false;
}
}
/**
* Your WordDictionary object will be instantiated and called as such:
* WordDictionary obj = new WordDictionary();
* obj.AddWord(word);
* bool param_2 = obj.Search(word);
*/
}
Please review my design and performance.
word[i]
\$\endgroup\$