雙陣列字典樹
阿新 • • 發佈:2021-10-09
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define MAX_N 26 typedef struct Node { int flag; struct Node *next[MAX_N]; } Node; void clear(Node *root) { if (!root) return ; for (int i = 1; i < MAX_N; i++) clear(root->next[i]); free(root); return ; } int node_cnt = 0; Node *getNewNode() { ++node_cnt; Node *p = (Node *)malloc(sizeof(Node)); p->flag = 0; for (int i = 0; i < MAX_N; i++) p->next[i] = 0; return p; } Node *insert(Node *root, char *a) { if (!root) root = getNewNode(); Node *p = root; for (int i = 0; a[i]; i++) { p->next[a[i] - 'a'] || (p->next[a[i] - 'a'] = getNewNode()); p = p->next[a[i] - 'a']; } p->flag = 1; return root; } void output(Node *root, char *c, int s) { if (!root) return ; root->flag && (c[s] = 0, printf("%s\n", c)); for (int i = 0; i < MAX_N; i++) { c[s] = i + 'a'; root->next[i] && (output(root->next[i], c, s + 1), 0); } return ; } //--------------------------------字典樹轉雙陣列字典樹--------------------------------------------------------- typedef struct DB_Node { int base, check; } DB_Node; void setBaseValue(Node *root, DB_Node *tree, int ind) { int base = 0, i; while (1) { ++base; for (i = 0; i < MAX_N; i++) { if (!root->next[i]) continue; //選擇空位,且不能是本身 if (!tree[base + i].check && !tree[base + i].base && base + i - ind) continue; break; } if (i == MAX_N) break; } tree[ind].base = base; return ; } void transtorm_double_array_trie(Node *root, DB_Node *tree, int ind) { if (!root) return ; setBaseValue(root, tree, ind); for (int i = 0; i < MAX_N; i++) { if (!root->next[i]) continue; tree[tree[ind].base + i].check = root->next[i]->flag ? - (ind) : ind; transtorm_double_array_trie(root->next[i], tree, tree[ind].base + i); } return ; } int fin(DB_Node *root, char *a, int s, int ind) { printf("%c == base %d, check %d\n", *a, root[ind].base, root[ind].check); if (!s && root[ind].check < 0) return 1; if (!s) return 0; int nex = root[ind].base + a[0] - 'a'; // 下一個節點的check父節點編號的絕對值,是否是當前節點 if (abs(root[nex].check) != ind) return 0; return fin(root, a + 1, s - 1, nex); } int main() { int n; char buff[1000] = {0}; Node *root = getNewNode(); scanf("%d", &n); for (int i = 0; i < n; i++) ~scanf("%s", &buff), insert(root, buff); DB_Node *tree = (DB_Node *)calloc(node_cnt * MAX_N, sizeof(DB_Node)); transtorm_double_array_trie(root, tree, 1); while (~scanf("%s", buff)) printf("\n查詢%s == %d\n", buff, fin(tree, buff, strlen(buff), 1)); return 0; }