#include #include #include #include // +-----------+----------------------------------------------------- // | Constants | // +-----------+ #define ALPHA 26 // +-------+--------------------------------------------------------- // | Types | // +-------+ struct Trie { int count; // # descendants struct Trie *children[ALPHA]; // links to children }; typedef struct Trie Trie; typedef struct Trie TrieNode; // +--------------------+-------------------------------------------- // | Utility Procedures | // +--------------------+ /** * Create a new, empty, trie. */ Trie * trie_new () { // Allocate Trie *t = malloc (sizeof (Trie)); // Sanity check if (NULL == t) return NULL; // Fill in count t->count = 0; // Fill in null children for (int i = 0; i < ALPHA; i++) { t->children[i] = NULL; } // for return t; } // trie_new /** * Deallocate all the memory associated with a trie. */ void trie_free (Trie * trie) { if (trie == NULL) return; for (int i = 0; i < ALPHA; i++) { trie_free (trie->children[i]); } // for free (trie); } // trie_free /** * Add an element to the trie. * @pre: The element is not in the trie. * @pre: The element consists only of lowercase letters * @pre: trie is not null */ void trie_add (Trie *trie, char *str) { // Determine the start of the string. char ch = str[0]; // If we have a null trie, we've violated the preconditions if (NULL == trie) { fprintf (stderr, "Null trie\n"); return; } // If we have something not a lowercase letter, we've violated // the preconditions if ((ch != '\0') && ((ch < 'a') || (ch > 'z'))) { fprintf (stderr, "Invalid character: %c\n", ch); return; } // Update the count trie->count += 1; // If we've reached the end of the string, we're done if (0 == ch) { return; } // Otherwise, update the count and recurse else { // Determine the index of the child int child = ch - 'a'; // Make sure the child exists if (NULL == trie->children[child]) trie->children[child] = trie_new (); // And recurse trie_add (trie->children[child], str+1); } } // add /** * Look up a prefix in the trie. */ int trie_lookup (Trie *trie, char *str) { // Determine the start of the string. char ch = str[0]; // If we have a null trie, it's not in the trie if (NULL == trie) { return 0; } // If we have something not a lowercase letter, there's no prefix if ((ch < 'a') || (ch > 'z')) { return 0; } // If we've reached the end of the string, we're done if (0 == ch) { return trie->count; } // Otherwise, recurse else { // Determine the index of the child int child = ch - 'a'; // Make sure the child exists if (NULL == trie->children[child]) return 0; // And recurse return trie_lookup (trie->children[child], str+1); } // fprintf (stderr, "Lookup %s\n", str); return 0; } // lookup // +------+---------------------------------------------------------- // | Main | // +------+ int main() { int numlines; char command[5]; char str[32]; // They say 21, but let's use a power of 2 for fun. Trie *trie = trie_new (); scanf ("%d", &numlines); for (int i = 0; i < numlines; i++) { scanf ("%s", command); scanf ("%s", str); if (strcmp (command, "add") == 0) trie_add (trie, str); else if (strcmp (command, "find") == 0) printf ("%d\n", trie_lookup (trie, str)); } // Cleanup trie_free (trie); return 0; } // main