zoukankan      html  css  js  c++  java
  • Leetcode: Add and Search Word

    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.

    方法1:brute force: search function compares each word with the pattern, time complexity: O(nk), n is number of words in dictionary, k is averge length

    方法2: trie, search use recursion, time complexity: O(nk)? space O(nk)?

    This is related to previous problem: Implement Trie

    Only because in this problem, "." is introduced, which will cause us to backtrack to check each son. Using iteration is not that convient, we use recursion here.

    One thing to be cautious is that when inserting words to a trie, the last node should have node.isEnd set to be true. Always forget this

     1 public class WordDictionary {
     2     public class TrieNode {
     3         int num; //count how many words go through this TrieNode
     4         TrieNode[] sons; //Arrays of children
     5         boolean isEnd;
     6         char val;
     7         
     8         public TrieNode() {
     9             this.num = 0;
    10             this.sons = new TrieNode[26];
    11             this.isEnd = false;
    12         }
    13     }
    14     
    15     TrieNode root;
    16     
    17     public WordDictionary() {
    18         this.root = new TrieNode();
    19     }
    20 
    21     // Adds a word into the data structure.
    22     public void addWord(String word) {
    23         if (word==null || word.length()==0) return;
    24         char[] arr = word.toCharArray();
    25         TrieNode node = this.root;
    26         for (char c : arr) {
    27             int pos = (int)(c - 'a');
    28             if (node.sons[pos] == null) {
    29                 node.sons[pos] = new TrieNode();
    30                 node.sons[pos].num = 1;
    31                 node.sons[pos].val = c;
    32             }
    33             else {
    34                 node.sons[pos].num++;
    35             }
    36             node = node.sons[pos];
    37         }
    38         node.isEnd = true;
    39     }
    40 
    41     // Returns if the word is in the data structure. A word could
    42     // contain the dot character '.' to represent any one letter.
    43     public boolean search(String word) {
    44         int len = word.length();
    45         TrieNode node = this.root;
    46         return search(word, node, 0, len);
    47     }
    48     
    49     public boolean search(String word, TrieNode node, int cur, int len) {
    50         if (cur == len) return node.isEnd;
    51         char w = word.charAt(cur);
    52         if (w == '.') {
    53             for (int j=0; j<26; j++) {
    54                 if (node.sons[j] != null) {
    55                     if (search(word, node.sons[j], cur+1, len))
    56                         return true;
    57                 }
    58             }
    59             return false;
    60         }
    61         else {
    62             int pos = (int)(w - 'a');
    63             if (node.sons[pos] == null) return false;
    64             return search(word, node.sons[pos], cur+1, len);
    65         }
    66     }
    67 }
    68 
    69 // Your WordDictionary object will be instantiated and called as such:
    70 // WordDictionary wordDictionary = new WordDictionary();
    71 // wordDictionary.addWord("word");
    72 // wordDictionary.search("pattern");

    Follow Up: any other solution?

    1. Preprocess the dictionary, store map<key, set<words>>, key is the pattern, like ".a.e.c", time complexity O(1), space complexity O(2^k), k is average word length

    2. still use trie, but for each trieNode, introduce a child '.', in the meanwhile maintain a set of words matched by current prefix, time complexity O(k), space: each level's space will be twice the orignal trie's space of this level.

    Follow Up: 如果现在word里面包含的不再是'.', 而是‘*’, 能match 0个到多个字符,问该怎么处理?

     1     public boolean search(String word, TrieNode node, int cur, int len) {
     2         if (cur == len) return node.isEnd;
     3         char w = word.charAt(cur);
     4         if (w == '*') {
     5             if (search(word, node, cur+1, len)) return true; //'*' match zero char
     6             for (int j=0; j<26; j++) {
     7                 if (node.sons[j] != null) {
     8                     if (search(word, node.sons[j], cur, len)) //skip one TrieNode, search next level, so '*' match 1 or more chars
     9                         return true;
    10                 }
    11             }
    12             return false;
    13         }
    14         else {
    15             int pos = (int)(w - 'a');
    16             if (node.sons[pos] == null) return false;
    17             return search(word, node.sons[pos], cur+1, len);
    18         }
    19     }

     完整代码在这里:

     1 package GooglePhone;
     2 
     3 
     4 public class Solution {
     5     public class TrieNode {
     6         int num; //count how many words go through this TrieNode
     7         TrieNode[] sons; //Arrays of children
     8         boolean isEnd;
     9         char val;
    10         
    11         public TrieNode() {
    12             this.num = 0;
    13             this.sons = new TrieNode[26];
    14             this.isEnd = false;
    15         }
    16     }
    17     
    18     TrieNode root;
    19     
    20     public Solution() {
    21         this.root = new TrieNode();
    22     }
    23 
    24     // Adds a word into the data structure.
    25     public void addWord(String word) {
    26         if (word==null || word.length()==0) return;
    27         char[] arr = word.toCharArray();
    28         TrieNode node = this.root;
    29         for (char c : arr) {
    30             int pos = (int)(c - 'a');
    31             if (node.sons[pos] == null) {
    32                 node.sons[pos] = new TrieNode();
    33                 node.sons[pos].num = 1;
    34                 node.sons[pos].val = c;
    35             }
    36             else {
    37                 node.sons[pos].num++;
    38             }
    39             node = node.sons[pos];
    40         }
    41         node.isEnd = true;
    42     }
    43 
    44     // Returns if the word is in the data structure. A word could
    45     // contain the dot character '.' to represent any one letter.
    46     public boolean search(String word) {
    47         int len = word.length();
    48         TrieNode node = this.root;
    49         return search(word, node, 0, len);
    50     }
    51     
    52     public boolean search(String word, TrieNode node, int cur, int len) {
    53         if (cur == len) return node.isEnd;
    54         char w = word.charAt(cur);
    55         if (w == '*') {
    56             if (search(word, node, cur+1, len)) return true; //'*' match zero char
    57             for (int j=0; j<26; j++) {
    58                 if (node.sons[j] != null) {
    59                     if (search(word, node.sons[j], cur, len)) //skip one TrieNode, search next level, so '*' match 1 or more chars
    60                         return true;
    61                 }
    62             }
    63             return false;
    64         }
    65         else {
    66             int pos = (int)(w - 'a');
    67             if (node.sons[pos] == null) return false;
    68             return search(word, node.sons[pos], cur+1, len);
    69         }
    70     }
    71     
    72     
    73     public static void main(String[] args) {
    74         // TODO Auto-generated method stub
    75         Solution sol = new Solution();
    76         sol.addWord("food");
    77         sol.addWord("hello");
    78         boolean res = sol.search("*f*d");
    79         if (res) System.out.println("true");
    80         else System.out.println("false");
    81     }
    82 }
    83 
    84 // Your WordDictionary object will be instantiated and called as such:
    85 // WordDictionary wordDictionary = new WordDictionary();
    86 // wordDictionary.addWord("word");
    87 // wordDictionary.search("pattern");

    The current adopted way of implement Trie: without val and num field

     1 class TrieNode {
     2     TrieNode[] children;
     3     boolean isWord;
     4     public TrieNode() {
     5         this.children = new TrieNode[26];
     6         this.isWord = false;
     7     }
     8 }
     9 
    10 class WordDictionary {
    11     TrieNode root;
    12 
    13     /** Initialize your data structure here. */
    14     public WordDictionary() {
    15         this.root = new TrieNode();
    16     }
    17     
    18     /** Adds a word into the data structure. */
    19     public void addWord(String word) {
    20         if (word == null || word.length() == 0) return;
    21         TrieNode cur = this.root;
    22         for (int i = 0; i < word.length(); i ++) {
    23             if (cur.children[word.charAt(i) - 'a'] == null) {
    24                 cur.children[word.charAt(i) - 'a'] = new TrieNode();
    25             }
    26             cur = cur.children[word.charAt(i) - 'a'];
    27         }
    28         cur.isWord = true;
    29     }
    30     
    31     /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
    32     public boolean search(String word) {
    33         if (word == null || word.length() == 0) return true;
    34         return match(word, 0, root);
    35     }
    36     
    37     public boolean match(String word, int pos, TrieNode cur) {
    38         if (pos == word.length()) {
    39             return cur.isWord;
    40         }
    41         if (word.charAt(pos) == '.') {
    42             for (int i = 0; i < 26; i ++) {
    43                 if (cur.children[i] == null) continue;
    44                 if (match(word, pos + 1, cur.children[i])) return true;
    45             }
    46             return false;
    47         }
    48         // for case where word.charAt(pos) != '.'
    49         if (cur.children[word.charAt(pos) - 'a'] != null) {
    50             return match(word, pos + 1, cur.children[word.charAt(pos) - 'a']);
    51         }
    52         return false;
    53     }
    54 }
    55 
    56 /**
    57  * Your WordDictionary object will be instantiated and called as such:
    58  * WordDictionary obj = new WordDictionary();
    59  * obj.addWord(word);
    60  * boolean param_2 = obj.search(word);
    61  */
  • 相关阅读:
    Apache ab压力测试时出现大量的错误原因分析
    图解linux下的top命令
    [转载]几种切词工具的使用(转)
    大规模中文文本处理中的自动切词和标注技术
    [转载]盘点:94版《三国演义》演员的今昔对比照
    搜索引擎切词详解
    iphone-命令行编译之--xcodebuild
    Appium IOS 自动化测试初探
    手把手教你appium_mac上环境搭建
    Appium-doctor 检测Xcode未安装问题
  • 原文地址:https://www.cnblogs.com/EdwardLiu/p/5052887.html
Copyright © 2011-2022 走看看