Add and Search Word - Data structure design

Design a data structure that supports the following two operations:

  1. void addWord(word)
  2. 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:

  1. addWord("bad")
  2. addWord("dad")
  3. addWord("mad")
  4. search("pad") -> false
  5. search("bad") -> true
  6. search(".ad") -> true
  7. search("b..") -> true

Note:

You may assume that all words are consist of lowercase letters a-z.

You should be familiar with how a Trie works. If not, please work on this problem: Implement Trie (Prefix Tree) first.

Solution:

  1. public class WordDictionary {
  2. Trie trie = new Trie();
  3. // Adds a word into the data structure.
  4. public void addWord(String word) {
  5. trie.insert(word);
  6. }
  7. // Returns if the word is in the data structure. A word could
  8. // contain the dot character '.' to represent any one letter.
  9. public boolean search(String word) {
  10. return trie.search(word);
  11. }
  12. class TrieNode {
  13. // Initialize your data structure here.
  14. char c;
  15. boolean isLeaf;
  16. Map<Character, TrieNode> children = new HashMap<Character, TrieNode>();
  17. public TrieNode() {}
  18. public TrieNode(char c) { this.c = c; }
  19. }
  20. public class Trie {
  21. private TrieNode root;
  22. public Trie() {
  23. root = new TrieNode();
  24. }
  25. // Inserts a word into the trie.
  26. public void insert(String word) {
  27. Map<Character, TrieNode> children = root.children;
  28. for (int i = 0; i < word.length(); i++) {
  29. char c = word.charAt(i);
  30. if (!children.containsKey(c))
  31. children.put(c, new TrieNode(c));
  32. TrieNode t = children.get(c);
  33. if (i == word.length() - 1)
  34. t.isLeaf = true;
  35. children = t.children;
  36. }
  37. }
  38. // Returns if the word is in the trie.
  39. public boolean search(String word) {
  40. return dfs(root, word, 0);
  41. }
  42. private boolean dfs(TrieNode node, String word, int index) {
  43. if (node == null || index == word.length() && !node.isLeaf)
  44. return false;
  45. if (node.isLeaf && index == word.length())
  46. return true;
  47. char c = word.charAt(index);
  48. if (c == '.') {
  49. for (char ch = 'a'; ch <= 'z'; ch++) {
  50. if (dfs(node.children.get(ch), word, index + 1))
  51. return true;
  52. }
  53. return false;
  54. } else {
  55. return dfs(node.children.get(c), word, index + 1);
  56. }
  57. }
  58. }
  59. }
  60. // Your WordDictionary object will be instantiated and called as such:
  61. // WordDictionary wordDictionary = new WordDictionary();
  62. // wordDictionary.addWord("word");
  63. // wordDictionary.search("pattern");