LeetCode prefix and suffix search (prefix tree)

Posted by dreamdelerium on Mon, 18 Nov 2019 15:50:50 +0100

Description:

Given multiple words, the weight of words[i] is I.

Design a class WordFilter to implement the function WordFilter.f(String prefix, String suffix). This function returns the maximum weight of the word with prefix prefix and suffix suffix suffix. If there is no such word, return - 1.

Example:

input:
WordFilter(["apple"])
WordFilter.f("a", "e") // Return to 0
WordFilter.f("b", "") // Return to -1

Be careful:

The length of words is between [1, 15000].
For each test case, there will be a maximum of words.length calls to WordFilter.f.
The length of words[i] is between [1,10].
prefix, suffix is before [0, 10].
words[i] and prefix, suffix contains only lowercase letters.

Thought analysis:

This kind of word search generally uses prefix tree to process, that is, through the structure of prefix tree to store all word sets, reducing the purpose of repeated search when searching words. About prefix tree and its application Implementation and application of prefix tree

Step one: build a tree. Convert vector < string > & words to prefix tree
 Step 2: first, determine whether prefix prefix exists
 Step 3: in the subtree starting with prefixRoot, the suffix of the search word is the maximum weight of suffix
//Program representation of prefix tree
class TrieNode {
public:
	bool isWord;//Whether the current node ends with a word
	int weight = 0;//Weight only makes sense when isWord == true
	vector<TrieNode*> children;
	TrieNode() : isWord(false), children(26, nullptr), weight(0) {}
	~TrieNode() {
		for (TrieNode* child : children)
			if (child) delete child;
	}
};

class WordFilter {
public:
	TrieNode *trieRoot;//Constructed word prefix tree
    //Add a word and its weight to the tree
	void addWord(string &word, int weight) {
		TrieNode *ptr = trieRoot;//Scan the tree and insert word
		for (auto ch : word) {
			if (ptr->children[ch - 'a'] == NULL) {
				ptr->children[ch - 'a'] = new TrieNode();
			}
			ptr = ptr->children[ch - 'a'];
		}
		ptr->isWord = true;//Mark as word
		ptr->weight = weight;//Record weight
	}
	//Search the prefix tree of a word for the existence of prefix, and return the node corresponding to the prefix
	TrieNode *myFindPrefix(string &prefix){
		TrieNode *ptr = trieRoot;//Scan the tree
		for (auto ch : prefix){
			if (ptr->children[ch - 'a'] == NULL) {
                //Null if prefix does not exist
				return NULL;
			}
			else{
				ptr = ptr->children[ch - 'a'];
			}
		}
		return ptr;//Otherwise, return the node address at the end of prefix prefix
	}
    //In the subtree starting with prefixRoot, the suffix of the search word is the maximum weight of suffix
    void myFind(TrieNode *prefixRoot, string word, string &suffix, int &maxRes){
		if (prefixRoot->isWord && word.substr(word.size() - suffix.size()) == suffix){
            //If prefixRoot is the end of a word at this time, and the suffix of the word is suffix
			maxRes = max(maxRes, prefixRoot->weight);
		}
		int wordSize = word.size();
		word += 'a';
        //Attempt to search 26 non empty child nodes of prefixRoot
		for (int index = 0; index < 26; ++index){
			if (prefixRoot->children[index]){//Not empty
				word[wordSize] = 'a' + index;
				myFind(prefixRoot->children[index], word, suffix, maxRes);
			}
		}
	}
	WordFilter(vector<string>& words) {
        //Vector < string > & words to prefix tree
		trieRoot = new TrieNode();
		int wordsSize = words.size();
		for (int index = 0; index < wordsSize; ++index){
			addWord(words[index], index);
		}
	}
	
	int f(string prefix, string suffix) {
        //The first step is to determine whether prefix prefix exists
		TrieNode *prefixRoot = myFindPrefix(prefix);
		if (prefixRoot == NULL){
			return -1;
		}
        //In the subtree starting with prefixRoot, the suffix of the search word is the maximum weight of suffix
		int maxRes = -1;
		myFind(prefixRoot, prefix, suffix, maxRes);
		return maxRes;
	}
};

/**
 * Your WordFilter object will be instantiated and called as such:
 * WordFilter* obj = new WordFilter(words);
 * int param_1 = obj->f(prefix,suffix);
 */