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
.
You should be familiar with how a Trie works. If not, please work on this problem:
Implement Trie (Prefix Tree) first.
思路:字典树的改进版,其中不同之处在于‘.’即‘.’可以通配任意一个字符。所以查找时如果出现‘.’则要递归遍历所有可能的情况。
我的代码把递归和迭代揉到了一块,写的不是很清晰,最下面有只依靠递归的,逻辑很简洁,看看简洁版的那个吧。字典树是常用的数据结构,其他比较常用的用于查找字符串的数据结构还有哈希表、双数组字典树。
My:
class WordDictionary {
class TreeNode{
TreeNode[] leaf;
boolean[] flags;
public TreeNode(){
//a - z , '.'
leaf = new TreeNode[27];
flags = new boolean[27];
}
}
TreeNode root;
/** Initialize your data structure here. */
public WordDictionary() {
root = new TreeNode();
}
/** Adds a word into the data structure. */
public void addWord(String word) {
char[] chs = word.toLowerCase().toCharArray();
TreeNode n = root;
for(int i = 0 ; i < chs.length;i++){
if(chs[i] == '.'){
if(n.leaf[26] == null){
n.leaf[26] = new TreeNode();
}
if(i == chs.length - 1) n.flags[26] = true;
n = n.leaf[26];
}else {
if(n.leaf[chs[i]-'a'] == null){
n.leaf[chs[i]-'a'] = new TreeNode();
}
if(i == chs.length - 1) n.flags[chs[i]-'a'] = true;
n = n.leaf[chs[i]-'a'];
}
}
}
/** 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) {
if(word.length()<=0 || word.equals("")) return true;
return search_dfs(word, root, 0);
}
public boolean search_dfs(String word,TreeNode n,int index) {
if( n == null) return false;
String sub = word.substring(index);
char[] chs = sub.toLowerCase().toCharArray();
for(int a = 0 ;a < chs.length ; a++){
if(chs[a] == '.'){
if(a == chs.length -1){
for(int i = 0 ; i <= 26 ;i++){
if(n.flags[i] == true){
return true;
}
}
return false;
}
boolean res = false;
for(int i = 0; i <= 26 ; i++){
if(n.leaf[i] != null){
res = res || search_dfs(word, n.leaf[i], index+1);
if(res) break;
}
}
return res;
}else{
if(a == chs.length -1){
if(n.flags[chs[a] - 'a'] == true) return true;
return false;
}
if(n.leaf[chs[a] - 'a'] == null){
return false;
}else{
n = n.leaf[chs[a] - 'a'];
index++;
}
}
}
return false;
}
}
/**
* Your WordDictionary object will be instantiated and called as such:
* WordDictionary obj = new WordDictionary();
* obj.addWord(word);
* boolean param_2 = obj.search(word);
*/
简洁版:
class WordDictionary {
private static class TrieNode{
boolean isWord;
TrieNode[] children;
TrieNode(){
isWord = false;
children = new TrieNode[26];
}
}
TrieNode root;
/** Initialize your data structure here. */
public WordDictionary() {
root = new TrieNode();
}
/** Adds a word into the data structure. */
public void addWord(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++){
int j = word.charAt(i) - 'a';
if (node.children[j] == null){
node.children[j] = new TrieNode();
}
node = node.children[j];
}
node.isWord = true;
}
/** 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 dfs(word, root, 0);
}
private boolean dfs(String word, TrieNode node, int index){
if (index == word.length()){
return node.isWord;
}
if (word.charAt(index) == '.'){
for (TrieNode temp : node.children){
if (temp != null && dfs(word, temp, index + 1)) return true;
}
return false;
} else {
int i = word.charAt(index) - 'a';
TrieNode temp = node.children[i];
return temp != null && dfs(word, temp, index + 1);
}
}
}
/**
* Your WordDictionary object will be instantiated and called as such:
* WordDictionary obj = new WordDictionary();
* obj.addWord(word);
* boolean param_2 = obj.search(word);
*/