1. 程式人生 > 其它 >雙陣列字典樹

雙陣列字典樹

#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;
}