设计一个支持以下两种操作的数据结构:
void addWord(word)
bool search(word)
search(word) 可以搜索文字或正则表达式字符串,字符串只包含字母 . 或 a-z 。 . 可以表示任何一个字母。
示例:
addWord("bad")
addWord("dad")
addWord("mad")
search("pad") -> false
search("bad") -> true
search(".ad") -> true
search("b..") -> true
说明:
你可以假设所有单词都是由小写字母 a-z 组成的
题解:
- 前缀树建树参见:【LeetCode题解】208. 实现 Trie (前缀树)
- 区别在于处理通配符,可以利用Queue队列将每一层符合要求的结点入队,出现通配符时,将Queue中结点的下一层子结点全部入队,作为下一层待选序列
- 结束时如果队列中存在叶结点,则表示search到符合要求的结点
- 如下图:
class Node{
private Node[] nexts;
private final int R = 26;
boolean isEnd = false;
Node(){
nexts = new Node[R];
}
boolean contains(char ch){
return nexts[ch-'a']!=null;
}
Node get(char ch){
return nexts[ch-'a'];
}
void put(char ch, Node node){
nexts[ch-'a'] = node;
}
void setEnd(){
isEnd = true;
}
boolean getEnd(){
return isEnd;
}
void getChilds(Queue q){//将非空子节点入队
for(Node node: nexts){
if(node!=null){
q.offer(node);
}
}
}
}
class WordDictionary {
/** Initialize your data structure here. */
Node root = null;
public WordDictionary() {
//前缀树,当出现通配符的时候使用队列将下层字符全部入队
root = new Node();
}
/** Adds a word into the data structure. */
public void addWord(String word) {
Node node = root;
for(int i=0 ; i<word.length() ; i++){
char curr = word.charAt(i);
if(!node.contains(curr)){
node.put(curr,new Node());
}
node = node.get(curr);
}
node.setEnd();
}
/** 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) {
Node node = root;
Queue<Node> q = new LinkedList<>();//本层待选队列,筛去char不符的结点
q.offer(node);
for(int i=0 ; i<word.length() ; i++){
char curr = word.charAt(i);
int len = q.size();
if(curr == '.'){
for(int j=0 ; j<len ; j++){
node = q.poll();
node.getChilds(q);//出现通配符,将子节点全部入队
}
}else{
for(int j=0 ; j<len ; j++){
node = q.poll();
if(node.contains(curr)){
q.offer(node.get(curr));
}
}
}
}
if(q.isEmpty()){
return false;
}else{
int len = q.size();
for(int i=0 ; i<len ; i++){
node = q.poll();
if(node.getEnd()){
return true;//是否存在一个结点是尾结点
}
}
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);
*/