// C implementation of search and insert operations // on Trie #include #include #include #include #define pi(x) printf("%s = %d\n", #x, x); #define pc(x) printf("%s = %c\n", #x, x); #define pp(x) printf("%s = %p\n", #x, x); #define ps(x) printf("%s = %s\n", #x, x); #define pb(x) printf("%s = %s\n", #x, x==true?"true":"false"); struct regex_string_structure { char * string; int index; int len; int malloced; }; struct regex_string { char * string; int index; int len; int malloced; }; #define str_malloc_(y, z) \ (y).string = malloc(z); \ memset((y).string, 0, z); \ (y).malloced = z; \ (y).len = 0; \ (y).index = 0; #define str_mallocr(y, z) \ str_malloc_((y), z); \ #define str_malloc(y, z) \ struct regex_string y; \ str_mallocr((y), z); #define str_new(str) \ str_malloc(str, 1) \ #define str_free_(y) \ memset((y).string, 0, (y).malloced); \ free((y).string); \ (y).string = NULL; \ (y).malloced = 0; \ (y).len = 0; \ (y).index = 0; \ #define str_free(y) \ { \ str_free_((y)); \ } #define str_reset_(str) { \ str_free_((str)) \ str_malloc_((str), 1) \ } #define str_reset(str) { \ str_reset_((str)) \ } #define str_realloc(y, z) \ (y).string = realloc((y).string, z); \ if ((y).malloced < z) { \ memset((y).string+(y).malloced, 0, (z)-(y).malloced); \ } \ (y).malloced = z; #define str_insert_char(str, ch) { \ str_realloc((str), (str).malloced+2); \ (str).string[(str).index] = ch; \ (str).index++; \ (str).string[(str).index] = 0; \ (str).len = strlen((str).string); \ } #define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0]) // 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]; int idx; // isEndOfWord is true if the node represents // end of a word bool isEndOfWord; }; // Returns new trie node (initialized to NULLs) struct TrieNode *getNode(int idx) { struct TrieNode *pNode = NULL; pNode = (struct TrieNode *)malloc(sizeof(struct TrieNode)); if (pNode) { int i; pNode->isEndOfWord = false; pNode->idx = idx; for (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 char *key, int dest_idx) { int level; int length = strlen(key); int index; struct TrieNode *pCrawl = root; for (level = 0; level < length; level++) { index = CHAR_TO_INDEX(key[level]); if (!pCrawl->children[index]) pCrawl->children[index] = getNode(dest_idx); else pCrawl->children[index]->idx = dest_idx; pCrawl = pCrawl->children[index]; } // mark last node as leaf pCrawl->isEndOfWord = true; } // Returns true if key presents in trie, else false bool search(struct TrieNode *root, const char *key, int idx) { int level; int length = strlen(key); int index; struct TrieNode *pCrawl = root; pi(idx); for (level = 0; level < length; level++) { index = CHAR_TO_INDEX(key[level]); if (!pCrawl->children[index]) { index = CHAR_TO_INDEX('x'); if (!pCrawl->children[index]) return false; } pCrawl = pCrawl->children[index]; } pi(pCrawl->idx); return (pCrawl != NULL && pCrawl->isEndOfWord && pCrawl->idx == idx); } // Returns true if key presents in trie, else false bool search_segmented(struct TrieNode *root, struct TrieNode *segments, const char *key) { int level; int length = strlen(key); int index; struct TrieNode *pCrawl = root; str_new(segment); int idx = 0; for (level = 0; level < length; level++) { str_insert_char(segment, key[level]); ps(segment.string); pb(search(segments, segment.string, idx)); if (search(segments, segment.string, idx)) { str_reset(segment); idx++; } index = CHAR_TO_INDEX(key[level]); if (!pCrawl->children[index]) { index = CHAR_TO_INDEX('x'); if (!pCrawl->children[index]) return false; } pCrawl = pCrawl->children[index]; } str_free(segment); return (pCrawl != NULL && pCrawl->isEndOfWord); } #define isp(root, segments, c) printf("%s --- %s\n", c, output[search_segmented(root, segments, c)] ) // Driver int main() { char output[][32] = {"Not present in trie", "Present in trie"}; struct TrieNode *root = getNode(0); struct TrieNode *segments = getNode(0); // Construct trie insert(segments, "0011", 0); insert(segments, "001", 1); insert(segments, "0", 2); insert(root, "00110010", 0); // Search for different keys isp(root, segments, "00110010"); return 0; }