(Classic Dictionary Tree) leetcode Medium 211. Adding and Searching Words - Data Structure Design

topic

Please design a data structure that supports adding new words and finding if a string matches any previously added string.

Implement the dictionary class WordDictionary:

WordDictionary() Initializes the dictionary object
void addWord(word) Adds word to the data structure, which can then be matched against
bool search(word) Returns true if a string matching word exists in the data structure; otherwise, returns false. word may contain some '.', each . can represent any letter.

Example:

输入:
[“WordDictionary”,“addWord”,“addWord”,“addWord”,“search”,“search”,“search”,“search”]
[[],[“bad”],[“dad”],[“mad”],[“pad”],[“bad”],[“.ad”],[“b…”]]
输出:
[null,null,null,null,false,true,true,true]

解释:
WordDictionary wordDictionary = new WordDictionary();
wordDictionary.addWord(“bad”);
wordDictionary.addWord(“dad”);
wordDictionary.addWord(“mad”);
wordDictionary.search(“pad”); // 返回 False
wordDictionary.search(“bad”); // 返回 True
wordDictionary.search(“.ad”); // 返回 True
wordDictionary.search(“b…”); // 返回 True

hint:

1 <= word.length <= 25
The word in addWord consists of lowercase English letters
The word in search consists of '.' or lowercase English letters
Up to 104 calls to addWord and search

Source: LeetCode
Link: https://leetcode-cn.com/problems/design-add-and-search-words-data-structure The
copyright belongs to Leetcode.com. For commercial reprints, please contact the official authorization, and for non-commercial reprints, please indicate the source.

analyze

Compared with the ordinary dictionary tree, this question has one more match of '.'. Here we can understand it as a wildcard. We can use a recursive method to search for ordinary letters and continue to search along it. When encountering wildcards, we can follow Deep search for all child nodes of its current node

code section

1. Construction of dictionary tree
#include <bits/stdc++.h>
#define MAXS 26
using namespace std;

struct TrieNode
{
    
    
	TrieNode *child[MAXS];
	bool isword;
	TrieNode ():isword(false)
	{
    
    
		for(int i=0;i<MAXS;i++)
			child[i]=NULL;
	}	
};
2. Insert words

Basic operation, judge character by character, generate if not, remember to mark the last position of the word

    void addWord(string word) {
    
    
		TrieNode *t=&_root;
		char *s=&word[0];
		while(*s)
		{
    
    
			int pos=*s-'a';
			if(!t->child[pos])
			{
    
    
				t->child[pos]=new TrieNode();
			}
			t=t->child[pos];
			s++;
		}
		t->isword=true;
    }
3. Look up words

Here is the core part of this topic. First, let's write what we can do now. There are two cases. One is '.' and the other is normal characters. When '.' The node performs a deep search, and the return false at the end is when the two conditions do not meet the conditions

		//现在能做的事情
		if(*s=='.')
		{
    
    
			for(int i=0;i<MAXS;i++)
			{
    
    
				if(t->child[i]&&search2(t->child[i],s+1))
					return true;
			}
		}
		else
		{
    
    
			int pos=*s-'a';
		 	if(t->child[pos]&&search2(t->child[pos],s+1))
		 		return true;
		}
		return false;

The next step is the exit. When the recursion reaches the point where we want to return, one of the characters currently judged does not exist, which we have hidden in what we can do, and then we judge the end of the string, we should judge the last Is the position of a letter a word

    	//出口
		if(*s=='\0')
		{
    
    
			return t->isword;
		}

full code

#include <bits/stdc++.h>
#define MAXS 26
using namespace std;

struct TrieNode
{
    
    
	TrieNode *child[MAXS];
	bool isword;
	TrieNode ():isword(false)
	{
    
    
		for(int i=0;i<MAXS;i++)
			child[i]=NULL;
	}	
};

class WordDictionary {
    
    
public:
	TrieNode _root;
    WordDictionary() {
    
    
		
    }
    
    void addWord(string word) {
    
    
		TrieNode *t=&_root;
		char *s=&word[0];
		while(*s)
		{
    
    
			int pos=*s-'a';
			if(!t->child[pos])
			{
    
    
				t->child[pos]=new TrieNode();
			}
			t=t->child[pos];
			s++;
		}
		t->isword=true;
    }
    
    bool search2(TrieNode *t,char *s)
    {
    
    
    	//出口
		if(*s=='\0')
		{
    
    
			return t->isword;
		}
		//现在能做的事情
		if(*s=='.')
		{
    
    
			for(int i=0;i<MAXS;i++)
			{
    
    
				if(t->child[i]&&search2(t->child[i],s+1))
					return true;
			}
		}
		else
		{
    
    
			int pos=*s-'a';
		 	if(t->child[pos]&&search2(t->child[pos],s+1))
		 		return true;
		}
		return false; 
	}
    
    bool search(string word) {
    
    
		TrieNode *t=&_root;
		char *s=&word[0];
		return search2(t,s);		
    }
};

int main (void)
{
    
    
	WordDictionary s;
	vector<string> str={
    
    "abc","ab"};
	for(int i=0;i<str.size();i++)
	{
    
    
		s.addWord(str[i]);
	}
	string s1=".b.";
	cout<<s.search(s1);
	
	return 0;
}







Summarize

If you don’t know the dictionary tree, this question will be a very terrifying existence. After learning the dictionary tree, it can be said to be a very basic question, so the data structure template used here must be very familiar, and it is best to be recited. It looks like this, so that when we encounter a problem, we don't have to think too much about the implementation details of the data structure.

Guess you like

Origin blog.csdn.net/weixin_46035615/article/details/124165111