$ ./trie_binary ----------------------------------------------------------------------->called init_aux() at line 348 from vcpu/../Shell/builtins/libstring.h ----------------------------------------------------------------------->called init_env() at line 327 from vcpu/../Shell/builtins/libstring.h ----------------------------------------------------------------------->called init_argX() at line 336 from vcpu/../Shell/builtins/libstring.h segment.string = 1 branch_index = 0 segments_curr = 0x55608c96c360 segments_prev = 0x55608c96c360 branch_index = 0 index = 1 level = 0 key[level] = 1 pCrawl = 0x55608c96c360 pCrawl->children = 0x55608c96c360 pCrawl->children[index] = 0x55608c96d420 pCrawl->next_count = 2 pCrawl->next = 0x55608c96d3a0 pCrawl->branch = true pCrawl->next[branch_index] = 0x55608c96c460 modifying root pCrawl->branch = true segments_curr = 0x55608c96c460 segments_prev = 0x55608c96c360 branches = true creating backtrack reference pCrawl = 0x55608c96c260 segments_curr = 0x55608c96c460 segments_prev = 0x55608c96c360 level = 0 index = 1 idx = 0 key = 12456 successfull idx = 0 result1 = true idx = 1 segment.string = 2 branch_index = 0 segments_curr = 0x55608c96c460 segments_prev = 0x55608c96c460 branch_index = 0 index = 2 level = 0 key[level] = 2 pCrawl = 0x55608c96c460 pCrawl->children = 0x55608c96c460 pCrawl->children[index] = 0x55608c96d5a0 pCrawl->next_count = 1 pCrawl->next = 0x55608c96d520 pCrawl->branch = false pCrawl->next[branch_index] = 0x55608c96c560 modifying root pCrawl->branch = false segments_curr = 0x55608c96c560 segments_prev = 0x55608c96c460 branches = false idx = 1 result1 = true idx = 2 segment.string = 4 branch_index = 0 segments_curr = 0x55608c96c560 segments_prev = 0x55608c96c560 branch_index = 0 index = 4 level = 0 key[level] = 4 pCrawl = 0x55608c96c560 pCrawl->children = 0x55608c96c560 pCrawl->children[index] = (nil) not found segments_curr = 0x55608c96c560 segments_prev = 0x55608c96c560 branches = false idx = 2 result1 = false loading last backtrack reference pCrawl = 0x55608c96cee0 segments = 0x55608c96c560 level = 3 index = 4 idx = 2 key = 12456 Backtrack_node->pCrawl = 0x55608c96c260 Backtrack_node->segments = 0x55608c96c360 Backtrack_node->level = 0 Backtrack_node->index = 1 Backtrack_node->idx = 0 Backtrack_node->key = 12456 segment.string = 1 branch_index = 1 segments_curr = 0x55608c96c360 segments_prev = 0x55608c96c360 branch_index = 1 index = 1 level = 0 key[level] = 1 pCrawl = 0x55608c96c360 pCrawl->children = 0x55608c96c360 pCrawl->children[index] = 0x55608c96d420 pCrawl->next_count = 2 pCrawl->next = 0x55608c96d3a0 pCrawl->branch = true pCrawl->next[branch_index] = 0x55608c96c860 modifying root pCrawl->branch = true segments_curr = 0x55608c96c860 segments_prev = 0x55608c96c360 branches = true creating backtrack reference pCrawl = 0x55608c96c260 segments_curr = 0x55608c96c860 segments_prev = 0x55608c96c360 level = 0 index = 1 idx = 0 key = 12456 successfull idx = 0 result1 = true idx = 1 segment.string = 2 branch_index = 0 segments_curr = 0x55608c96c860 segments_prev = 0x55608c96c860 branch_index = 0 index = 2 level = 0 key[level] = 2 pCrawl = 0x55608c96c860 pCrawl->children = 0x55608c96c860 pCrawl->children[index] = 0x55608c96e060 pCrawl->next_count = 1 pCrawl->next = 0x55608c96cce0 pCrawl->branch = false pCrawl->next[branch_index] = 0x55608c96c960 modifying root pCrawl->branch = false segments_curr = 0x55608c96c960 segments_prev = 0x55608c96c860 branches = false idx = 1 result1 = true idx = 2 segment.string = 4 branch_index = 0 segments_curr = 0x55608c96c960 segments_prev = 0x55608c96c960 branch_index = 0 index = 4 level = 0 key[level] = 4 pCrawl = 0x55608c96c960 pCrawl->children = 0x55608c96c960 pCrawl->children[index] = 0x55608c96e1e0 pCrawl->next_count = 1 pCrawl->next = 0x55608c96e160 pCrawl->branch = false pCrawl->next[branch_index] = 0x55608c96ca60 modifying root pCrawl->branch = false segments_curr = 0x55608c96ca60 segments_prev = 0x55608c96c960 branches = false idx = 2 result1 = true idx = 3 segment.string = 5 branch_index = 0 segments_curr = 0x55608c96ca60 segments_prev = 0x55608c96ca60 branch_index = 0 index = 5 level = 0 key[level] = 5 pCrawl = 0x55608c96ca60 pCrawl->children = 0x55608c96ca60 pCrawl->children[index] = 0x55608c96e360 pCrawl->next_count = 1 pCrawl->next = 0x55608c96e2e0 pCrawl->branch = false pCrawl->next[branch_index] = 0x55608c96cb60 modifying root pCrawl->branch = false segments_curr = 0x55608c96cb60 segments_prev = 0x55608c96ca60 branches = false idx = 3 result1 = true idx = 4 segment.string = 6 branch_index = 0 segments_curr = 0x55608c96cb60 segments_prev = 0x55608c96cb60 branch_index = 0 index = 6 level = 0 key[level] = 6 pCrawl = 0x55608c96cb60 pCrawl->children = 0x55608c96cb60 pCrawl->children[index] = 0x55608c96e4e0 pCrawl->next_count = 1 pCrawl->next = 0x55608c96e460 pCrawl->branch = false pCrawl->next[branch_index] = (nil) pCrawl->branch = false segments_curr = 0x55608c96cb60 segments_prev = 0x55608c96cb60 branches = false idx = 4 result1 = true idx = 5 12456 --- Present in trie $ cat trie_binary.c // C implementation of search and insert operations // on Trie #include #include #include #include #include "../Shell/builtins/printfmacro.h" #include "../Shell/builtins/regex_str.h" // backtracking history // A C program to demonstrate linked list based implementation of queue // A linked list (LL) node to store a queue entry struct Backtrack_QNode { struct TrieNode *pCrawl; struct TrieNode *segments; int level; int index; int idx; const char * key; struct Backtrack_QNode *next; }; // The queue, front stores the front node of LL and rear stores ths // last node of LL struct Backtrack_Queue { struct Backtrack_QNode *front, *rear; }; // A utility function to create a new linked list node. struct Backtrack_QNode* Backtrack_newNode(struct TrieNode *pCrawl, struct TrieNode *segments, int level, int index, int idx, const char * key) { struct Backtrack_QNode *temp = (struct Backtrack_QNode*)malloc(sizeof(struct Backtrack_QNode)); temp->pCrawl = pCrawl; temp->segments = segments; temp->level = level; temp->index = index; temp->idx = idx; temp->key = key; temp->next = NULL; return temp; } // A utility function to create an empty queue struct Backtrack_Queue *Backtrack_createQueue() { struct Backtrack_Queue *q = (struct Backtrack_Queue*)malloc(sizeof(struct Backtrack_Queue)); q->front = q->rear = NULL; return q; } void Backtrack_store_asm(struct Backtrack_Queue **qq, struct TrieNode *pCrawl, struct TrieNode *segments, int level, int index, int idx, const char * key) { if (*qq == NULL) *qq = Backtrack_createQueue(); // Create a new LL node struct Backtrack_QNode *temp = Backtrack_newNode(pCrawl, segments, level, index, idx, key); // If queue is empty, then new node is front and rear both if ((*qq)->rear == NULL) { (*qq)->front = (*qq)->rear = temp; return; } // Add the new node at the end of queue and change rear temp->next = (*qq)->rear; (*qq)->rear = temp; } struct Backtrack_QNode * Backtrack_load_asm(struct Backtrack_Queue **qq) { if ((*qq) == NULL) return NULL; // If queue is empty, return NULL. if ((*qq)->rear == NULL) return NULL; // Store previous front and move front one node ahead struct Backtrack_QNode *temp = (*qq)->rear; (*qq)->rear = (*qq)->rear->next; // If front becomes NULL, then change rear also as NULL if ((*qq)->rear == NULL) (*qq)->front = NULL; return temp; } #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') #define INT_TO_INDEX(c) ((int)c - (int)'0') // trie node struct TrieNode { struct TrieNode *children[ALPHABET_SIZE]; int * idx; int count; bool branch; // isEndOfWord is true if the node represents // end of a word bool isEndOfWord; struct TrieNode ** next; int next_count; }; bool is_branch = true; bool is_not_branch = false; // Returns new trie node (initialized to NULLs) struct TrieNode *getNode(void) { struct TrieNode *pNode = NULL; pNode = (struct TrieNode *)malloc(sizeof(struct TrieNode)); if (pNode) { int i; pNode->isEndOfWord = false; pNode->idx = NULL; pNode->next = NULL; pNode->count = 0; 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, struct TrieNode *next) { int level; int length = strlen(key); int index; struct TrieNode *pCrawl = root; // pi(dest_idx) for (level = 0; level < length; level++) { // pi(level); // pc(key[level]) str_new(ch); str_insert_char(ch, key[level]); if (ch.type & STR_TYPE_DIGIT) index = INT_TO_INDEX(key[level]); else if (ch.type & STR_TYPE_ALPHABETIC) index = CHAR_TO_INDEX(key[level]); str_free(ch) // pi(index) // pp(pCrawl->children[index]) if (!pCrawl->children[index]) { pCrawl->children[index] = getNode(); } if (level == length-1) { // pp(pCrawl->children[index]) // pp(pCrawl->children[index]->idx) pCrawl->children[index]->next_count++; if (!pCrawl->children[index]->next) { pCrawl->children[index]->next = malloc(sizeof(int*)*pCrawl->children[index]->next_count); // pp(pCrawl->children[index]->idx) } else { pCrawl->children[index]->next = realloc(pCrawl->children[index]->next, sizeof(int*)*pCrawl->children[index]->next_count); } pCrawl->children[index]->next[pCrawl->children[index]->next_count-1] = next; if (pCrawl->children[index]->next_count > 1) pCrawl->children[index]->branch = true; pCrawl->children[index]->count++; if (!pCrawl->children[index]->idx) { pCrawl->children[index]->idx = malloc(sizeof(int*)*pCrawl->children[index]->count); // pp(pCrawl->children[index]->idx) } else { pCrawl->children[index]->idx = realloc(pCrawl->children[index]->idx, sizeof(int*)*pCrawl->children[index]->count); } pCrawl->children[index]->idx[pCrawl->children[index]->count-1] = dest_idx; // pi(pCrawl->children[index]->idx[pCrawl->children[index]->count-1]) } 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, bool * branches, int branch_index) { int level; int length = strlen(key); int index; struct TrieNode *pCrawl = *root; // pi(idx); for (level = 0; level < length; level++) { str_new(ch); str_insert_char(ch, key[level]); if (ch.type & STR_TYPE_DIGIT) index = INT_TO_INDEX(key[level]); else if (ch.type & STR_TYPE_ALPHABETIC) index = CHAR_TO_INDEX(key[level]); str_free(ch) pi(branch_index) pi(index) pi(level) pc(key[level]) pp(pCrawl) pp(pCrawl->children) pp(pCrawl->children[index]) if (!pCrawl->children[index]) { index = CHAR_TO_INDEX('x'); if (!pCrawl->children[index]) { puts("not found"); return false; } } pCrawl = pCrawl->children[index]; pi(pCrawl->next_count); if (branch_index > pCrawl->next_count-1) { puts("error, branch index is greater than branch count"); abort(); } pp(pCrawl->next); pb(pCrawl->branch); *branches = pCrawl->branch; if (pCrawl->next) { pp(pCrawl->next[branch_index]); if (pCrawl->next[branch_index]) { puts("modifying root"); *root = pCrawl->next[branch_index]; } } } // pi(pCrawl->count) bool final_match = false; for (int i = 0; i < pCrawl->count; i++) { // pi(pCrawl->idx[i]) if (pCrawl->idx[i] == idx) final_match = true; } // pb(final_match) pb(pCrawl->branch); return (pCrawl != NULL && pCrawl->isEndOfWord && final_match); } // 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; int branch_index = 0; struct TrieNode *pCrawl = root; str_new(segment); int idx = 0; int undo = 0; bool next_reload = false; struct Backtrack_Queue * Backtrack_queue = NULL; for (level = 0; level < length; level++) { if (next_reload == true) { puts("loading last backtrack reference"); struct Backtrack_QNode * Backtrack_node = NULL; \ Backtrack_node = Backtrack_load_asm(&Backtrack_queue); if (Backtrack_node) { pp(pCrawl) pp(segments) pi(level) pi(index) pi(idx) ps(key) pp(Backtrack_node->pCrawl) pp(Backtrack_node->segments) pi(Backtrack_node->level) pi(Backtrack_node->index) pi(Backtrack_node->idx) ps(Backtrack_node->key) for (int i = 0; i < undo; i++) { str_undo_(segment); } undo = 0; pCrawl = Backtrack_node->pCrawl; segments = Backtrack_node->segments; level = Backtrack_node->level; index = Backtrack_node->index; idx = Backtrack_node->idx; key = Backtrack_node->key; branch_index++; } } str_new(ch); str_insert_char(ch, key[level]); if (ch.type & STR_TYPE_DIGIT) index = INT_TO_INDEX(key[level]); else if (ch.type & STR_TYPE_ALPHABETIC) index = CHAR_TO_INDEX(key[level]); str_free(ch) str_insert_char(segment, key[level]); ps(segment.string); // pp(segments) bool branches = false; pi(branch_index); struct TrieNode *segments_prev = segments, *segments_curr = segments; pp(segments_curr) pp(segments_prev) bool result1 = search(&segments, segment.string, idx, &branches, branch_index); segments_curr = segments; pp(segments_curr) pp(segments_prev) pb(branches) if (branches) { // store a backtrack reference to this branch puts("creating backtrack reference"); pp(pCrawl) pp(segments_curr) pp(segments_prev) pi(level) pi(index) pi(idx) ps(key) Backtrack_store_asm(&Backtrack_queue, pCrawl, segments_prev, level, index, idx, key); puts("successfull"); } // pp(segments) pi(idx) pb(result1); undo++; next_reload = false; if (result1) { str_reset(segment); idx++; undo = 0; branch_index = 0; } else { next_reload = true; continue; } // sleep(5); pi(idx) 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"}; /* // Construct trie insert(segments, "0011", 0, segments1); pp(segments->next) insert(segments1, "001", 1, NULL); insert(segments1, "0", 2, NULL); insert(segments1, "0", 3, NULL); insert(root, "001100100", 0, NULL); // Search for different keys isp(root, segments, "001100100"); */ // Construct trie /* shall aim to be equivilant to this rule_1 ::= "1" "0"; rule_2 ::= "0" "1"; rule_3 ::= "0" "0"; */ // rule 1 // when adding a new rule indexing resets to 0 struct TrieNode *root = getNode(); struct TrieNode *sub_root = getNode(); struct TrieNode *rule_1 = getNode(); struct TrieNode *rule_2 = getNode(); struct TrieNode *rule_3 = getNode(); struct TrieNode *rule_4 = getNode(); struct TrieNode *rule_5 = getNode(); struct TrieNode *rule_6 = getNode(); struct TrieNode *rule_7 = getNode(); struct TrieNode *rule_8 = getNode(); insert(root, "12356", 0, NULL); insert(sub_root, "1", 0, rule_1); insert(rule_1, "2", 1, rule_2); insert(rule_2, "3", 2, rule_3); insert(rule_3, "5", 3, rule_4); insert(rule_4, "6", 4, NULL); insert(root, "12456", 0, NULL); insert(sub_root, "1", 0, rule_5); insert(rule_5, "2", 1, rule_6); insert(rule_6, "4", 2, rule_7); insert(rule_7, "5", 3, rule_8); insert(rule_8, "6", 4, NULL); // Search for different keys // isp(root, sub_root, "12356"); isp(root, sub_root, "12456"); // isp(root, sub_root, "12356"); return 0; } /* adding rule 1: segments [0, 1, 0] root [010] adding rule 2: segments [0, 1, 1] root [011] segment.string = 0 result = true segment.string = 1 result = true segment.string = 0 result = false 010 --- Present in trie segment.string = 0 result = true segment.string = 1 result = true segment.string = 1 result = true 011 --- Present in trie */