Created
January 15, 2020 16:53
-
-
Save SuryaPratapK/18a297d09739dffb4aa84ecfaa237803 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// C++ program to demonstrate auto-complete feature | |
// using Trie data structure. | |
#include<bits/stdc++.h> | |
using namespace std; | |
// Alphabet size (# of symbols) | |
#define ALPHABET_SIZE (26) | |
// Converts key current character into index | |
// use only 'a' through 'z' and lower case | |
#define CHAR_TO_INDEX(c) ((int)c - (int)'a') | |
// trie node | |
struct TrieNode | |
{ | |
struct TrieNode *children[ALPHABET_SIZE]; | |
// isWordEnd is true if the node represents | |
// end of a word | |
bool isWordEnd; | |
}; | |
// Returns new trie node (initialized to NULLs) | |
struct TrieNode *getNode(void) | |
{ | |
struct TrieNode *pNode = new TrieNode; | |
pNode->isWordEnd = false; | |
for (int i = 0; i < ALPHABET_SIZE; i++) | |
pNode->children[i] = NULL; | |
return pNode; | |
} | |
// If not present, inserts key into trie. If the | |
// key is prefix of trie node, just marks leaf node | |
void insert(struct TrieNode *root, const string key) | |
{ | |
struct TrieNode *pCrawl = root; | |
for (int level = 0; level < key.length(); level++) | |
{ | |
int index = CHAR_TO_INDEX(key[level]); | |
if (!pCrawl->children[index]) | |
pCrawl->children[index] = getNode(); | |
pCrawl = pCrawl->children[index]; | |
} | |
// mark last node as leaf | |
pCrawl->isWordEnd = true; | |
} | |
// Returns true if key presents in trie, else false | |
bool search(struct TrieNode *root, const string key) | |
{ | |
int length = key.length(); | |
struct TrieNode *pCrawl = root; | |
for (int level = 0; level < length; level++) | |
{ | |
int index = CHAR_TO_INDEX(key[level]); | |
if (!pCrawl->children[index]) | |
return false; | |
pCrawl = pCrawl->children[index]; | |
} | |
return (pCrawl != NULL && pCrawl->isWordEnd); | |
} | |
// Returns 0 if current node has a child | |
// If all children are NULL, return 1. | |
bool isLastNode(struct TrieNode* root) | |
{ | |
for (int i = 0; i < ALPHABET_SIZE; i++) | |
if (root->children[i]) | |
return 0; | |
return 1; | |
} | |
// Recursive function to print auto-suggestions for given | |
// node. | |
void suggestionsRec(struct TrieNode* root, string currPrefix) | |
{ | |
// found a string in Trie with the given prefix | |
if (root->isWordEnd) | |
{ | |
cout << currPrefix; | |
cout << endl; | |
} | |
// All children struct node pointers are NULL | |
if (isLastNode(root)) | |
return; | |
for (int i = 0; i < ALPHABET_SIZE; i++) | |
{ | |
if (root->children[i]) | |
{ | |
// append current character to currPrefix string | |
currPrefix.push_back(97 + i); | |
// recur over the rest | |
suggestionsRec(root->children[i], currPrefix); | |
} | |
} | |
} | |
// print suggestions for given query prefix. | |
int printAutoSuggestions(TrieNode* root, const string query) | |
{ | |
struct TrieNode* pCrawl = root; | |
// Check if prefix is present and find the | |
// the node (of last level) with last character | |
// of given string. | |
int level; | |
int n = query.length(); | |
for (level = 0; level < n; level++) | |
{ | |
int index = CHAR_TO_INDEX(query[level]); | |
// no string in the Trie has this prefix | |
if (!pCrawl->children[index]) | |
return 0; | |
pCrawl = pCrawl->children[index]; | |
} | |
// If prefix is present as a word. | |
bool isWord = (pCrawl->isWordEnd == true); | |
// If prefix is last node of tree (has no | |
// children) | |
bool isLast = isLastNode(pCrawl); | |
// If prefix is present as a word, but | |
// there is no subtree below the last | |
// matching node. | |
if (isWord && isLast) | |
{ | |
cout << query << endl; | |
return -1; | |
} | |
// If there are are nodes below last | |
// matching character. | |
if (!isLast) | |
{ | |
string prefix = query; | |
suggestionsRec(pCrawl, prefix); | |
return 1; | |
} | |
} | |
// Driver Code | |
int main() | |
{ | |
struct TrieNode* root = getNode(); | |
insert(root, "hello"); | |
insert(root, "dog"); | |
insert(root, "hell"); | |
insert(root, "cat"); | |
insert(root, "a"); | |
insert(root, "hel"); | |
insert(root, "help"); | |
insert(root, "helps"); | |
insert(root, "helping"); | |
int comp = printAutoSuggestions(root, "hel"); | |
if (comp == -1) | |
cout << "No other strings found with this prefix\n"; | |
else if (comp == 0) | |
cout << "No string found with this prefix\n"; | |
return 0; | |
} |
`void suggestionsRec(struct TrieNode* root, string& currPrefix)
{
// found a string in Trie with the given prefix
if (root->isWordEnd)
{
cout << currPrefix;
cout << endl;
}// All children struct node pointers are NULL if (isLastNode(root)) { currPrefix.pop_back(); return; } for (int i = 0; i < ALPHABET_SIZE; i++) { if (root->children[i]) { // append current character to currPrefix string currPrefix.push_back(97 + i); // recur over the rest suggestionsRec(root->children[i], currPrefix); } } currPrefix.pop_back();
}`
because it is called backtracking.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can you please explain the reason for this pop_back() ?
I also got the same problem before i see this, then i added pop_back and it worked.
I still did not understand the reason for this.
Because the currPrefix pass by value, so each recursive call should have its own coopy.
The below is my code. You see the line str.pop_back(); in printStrings() method.
void printStrings(node* root, string str)
{
}
The below is full implementation.
#include
#include
#include <unordered_map>
#include
#include
using namespace std;
struct node
{
unordered_map<char, node*> children;
};
node* newNode()
{
node* temp = new node;
return temp;
}
void insertString(string str, node* root)
{
node* crawler = root;
}
bool startsWith(string prefix, node* root)
{
if (!root->children.size())
return false;
}
bool searchStr(string str, node* root)
{
if (!root->children.size())
return false;
}
void printStrings(node* root, string str)
{
}
void testTrie()
{
node* root = newNode();
string str;
}