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.
基本和implement a trie没有区别,只是加入了最基本的regular expression. 一开始的版本TrieNode的next用arraylist实现,但是查找需要O(n), 第二版改成hashmap
[code] 第一版
public class WordDictionary {
Trie dict;
WordDictionary()
{
dict=new Trie();
}
// Adds a word into the data structure.
public void addWord(String word) {
dict.insert(word);
}
// Returns if the word is in the data structure. A word could
// contain the dot character '.' to represent any one letter.
public boolean search(String word) {
return dict.search(word);
}
}
class Trie
{
TrieNode root;
Trie()
{
root=new TrieNode('0');
}
void insert(String word)
{
if(word==null || word.length()==0)return;
int i=0;
TrieNode current=root;
while(i<word.length())
{
boolean found=false;
for(TrieNode node:current.next)
{
if(node!=null && node.value==word.charAt(i))
{
current=node;
i++;
found=true;
break;
}
}
if(found==false)
{
TrieNode node=new TrieNode(word.charAt(i));
current.next.add(node);
i++;
current=node;
}
}
current.next.add(null);
}
boolean search(String word)
{
return Trie.search(word, this.root);
}
static boolean search(String suffix, TrieNode start)
{
if(suffix==null || suffix.length()==0)return start.next.contains(null);
for(TrieNode node: start.next)
{
if(node!=null && (node.value==suffix.charAt(0) || suffix.charAt(0)=='.') )
{
if(search(suffix.substring(1,suffix.length()),node))return true;
}
}
return false;
}
}
class TrieNode
{
char value;
ArrayList<TrieNode> next;
TrieNode(char c)
{
value=c;
next=new ArrayList<TrieNode>();
}
}
// Your WordDictionary object will be instantiated and called as such:
// WordDictionary wordDictionary = new WordDictionary();
// wordDictionary.addWord("word");
// wordDictionary.search("pattern");
leafnode的key其实可以用null,因为hashmap支持null作为key
[code] 第二版
public class WordDictionary {
Trie dict;
WordDictionary()
{
dict=new Trie();
}
// Adds a word into the data structure.
public void addWord(String word) {
dict.insert(word);
}
// Returns if the word is in the data structure. A word could
// contain the dot character '.' to represent any one letter.
public boolean search(String word) {
return dict.search(word);
}
}
class Trie
{
TrieNode root;
Trie()
{
root=new TrieNode('0');
}
void insert(String word)
{
if(word==null || word.length()==0)return;
int i=0;
TrieNode current=root;
while(i<word.length())
{
char c=word.charAt(i);
if(current.next.containsKey(c)==false)
{
TrieNode node=new TrieNode(c);
current.next.put(c, node);
}
current=current.next.get(c);
i++;
}
current.next.put('$',null);
}
boolean search(String word)
{
return Trie.search(word, this.root);
}
static boolean search(String suffix, TrieNode start)
{
if(suffix==null || suffix.length()==0)return start.next.containsKey('$');
if(start.next.containsKey(suffix.charAt(0)))
{
return search(suffix.substring(1,suffix.length()),start.next.get(suffix.charAt(0)));
}
else if(suffix.charAt(0)=='.')
{
for(Character c:start.next.keySet())
{
if(c!='$')
{
if(search(suffix.substring(1,suffix.length()),start.next.get(c)))return true;
}
}
}
return false;
}
}
class TrieNode
{
char value;
HashMap<Character, TrieNode> next;
TrieNode(char c)
{
value=c;
next=new HashMap<Character, TrieNode>();
}
}
// Your WordDictionary object will be instantiated and called as such:
// WordDictionary wordDictionary = new WordDictionary();
// wordDictionary.addWord("word");
// wordDictionary.search("pattern");