pompeiifreckles

Autocomplete_trie

Nov 3rd, 2019
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.39 KB | None | 0 0
  1. // C program to demonstrate auto-complete feature
  2. // using Trie data structure.
  3. #include<stdio.h>
  4. #include<string.h>
  5. #include<stdlib.h>
  6.  
  7.  
  8. // Alphabet size (# of symbols)
  9. #define ALPHABET_SIZE (26)
  10.  
  11. // Converts key current character into index
  12. // use only 'a' through 'z' and lower case
  13. #define CHAR_TO_INDEX(c) ((int)c - (int)'a')
  14.  
  15. // trie node
  16. struct TrieNode
  17. {
  18.     struct TrieNode *children[ALPHABET_SIZE];
  19.  
  20.     // isWordEnd is true if the node represents
  21.     // end of a word
  22.     bool isWordEnd;
  23. };
  24.  
  25. // Returns new trie node (initialized to NULLs)
  26. struct TrieNode *getNode(void)
  27. {
  28.     struct TrieNode *pNode = (struct TrieNode *)malloc(sizeof(TrieNode));
  29.     pNode->isWordEnd = false;
  30.  
  31.     for (int i = 0; i < ALPHABET_SIZE; i++)
  32.         pNode->children[i] = NULL;
  33.  
  34.     return pNode;
  35. }
  36.  
  37. // If not present, inserts key into trie. If the
  38. // key is prefix of trie node, just marks leaf node
  39. void insert(struct TrieNode *root, const char * key)
  40. {
  41.     struct TrieNode *pCrawl = root;
  42.  
  43.     for (int level = 0; level < strlen(key); level++)
  44.     {
  45.         int index = CHAR_TO_INDEX(key[level]);
  46.         if (!pCrawl->children[index])
  47.             pCrawl->children[index] = getNode();
  48.  
  49.         pCrawl = pCrawl->children[index];
  50.     }
  51.  
  52.     // mark last node as leaf
  53.     pCrawl->isWordEnd = true;
  54. }
  55.  
  56. // Returns true if key presents in trie, else false
  57. bool search(struct TrieNode *root, const char * key)
  58. {
  59.     int length = strlen(key);
  60.     struct TrieNode *pCrawl = root;
  61.     for (int level = 0; level < length; level++)
  62.     {
  63.         int index = CHAR_TO_INDEX(key[level]);
  64.  
  65.         if (!pCrawl->children[index])
  66.             return false;
  67.  
  68.         pCrawl = pCrawl->children[index];
  69.     }
  70.  
  71.     return (pCrawl != NULL && pCrawl->isWordEnd);
  72. }
  73.  
  74. // Returns 0 if current node has a child
  75. // If all children are NULL, return 1.
  76. bool isLastNode(struct TrieNode* root)
  77. {
  78.     for (int i = 0; i < ALPHABET_SIZE; i++)
  79.         if (root->children[i])
  80.             return 0;
  81.     return 1;
  82. }
  83.  
  84. // Recursive function to print auto-suggestions for given
  85. // node.
  86. void suggestionsRec(struct TrieNode* root, char * currPrefix)
  87. {
  88.     // found a string in Trie with the given prefix
  89.    
  90.         static char * origCurr = strdup(currPrefix);   
  91.     if (root->isWordEnd)
  92.     {
  93.         printf("%s", currPrefix);
  94.             printf("\n");
  95.         strcpy(currPrefix, origCurr);  
  96.     }
  97.  
  98.     // All children struct node pointers are NULL
  99.     if (isLastNode(root))
  100.         return;
  101.  
  102.     char * temp;
  103.  
  104.     for (int i = 0; i < ALPHABET_SIZE; i++)
  105.     {
  106.         if (root->children[i])
  107.         {
  108.             // append current character to currPrefix string
  109.             temp = (char *)malloc(2);
  110.             temp[0] = 97+i;
  111.             temp[1] = 0;
  112.                 strcat(currPrefix, temp);
  113.             free(temp);
  114.  
  115.             // recur over the rest
  116.             suggestionsRec(root->children[i], currPrefix);
  117.         }
  118.     }
  119. }
  120.  
  121. // print suggestions for given query prefix.
  122. int printAutoSuggestions(TrieNode* root, const char * query)
  123. {
  124.     struct TrieNode* pCrawl = root;
  125.  
  126.     // Check if prefix is present and find the
  127.     // the node (of last level) with last character
  128.     // of given string.
  129.     int level;
  130.     int n = strlen(query);
  131.     for (level = 0; level < n; level++)
  132.     {
  133.         int index = CHAR_TO_INDEX(query[level]);
  134.  
  135.         // no string in the Trie has this prefix
  136.         if (!pCrawl->children[index])
  137.             return 0;
  138.  
  139.         pCrawl = pCrawl->children[index];
  140.     }
  141.  
  142.     // If prefix is present as a word.
  143.     bool isWord = (pCrawl->isWordEnd == true);
  144.  
  145.     // If prefix is last node of tree (has no
  146.     // children)
  147.     bool isLast = isLastNode(pCrawl);
  148.  
  149.     // If prefix is present as a word, but
  150.     // there is no subtree below the last
  151.     // matching node.
  152.     if (isWord && isLast)
  153.     {
  154.         printf("%s\n", query);
  155.         return -1;
  156.     }
  157.  
  158.     // If there are are nodes below last
  159.     // matching character.
  160.     if (!isLast)
  161.     {
  162.         char * prefix = strdup(query);
  163.         suggestionsRec(pCrawl, prefix);
  164.             free(prefix);  
  165.         return 1;
  166.     }
  167. }
  168.  
  169. // Driver Code
  170. int main()
  171. {
  172.     struct TrieNode* root = getNode();
  173.     insert(root, "facebook");
  174.     insert(root, "google");
  175.     insert(root, "nptel");
  176.     insert(root, "factchecker");
  177.     insert(root, "duckduckgo");
  178.     insert(root, "edx");
  179.     insert(root, "coursera");
  180.     insert(root, "facemash");
  181.     insert(root, "faceplusplus");
  182.     int comp = printAutoSuggestions(root, "fac");
  183.  
  184.     if (comp == -1)
  185.         printf( "No other strings found with this prefix\n");
  186.  
  187.     else if (comp == 0)
  188.         printf( "No string found with this prefix\n");
  189.  
  190.     free(root);
  191.     return 0;
  192. }
Add Comment
Please, Sign In to add comment