Trie(字典树)学习小结1

学了一个上午,勉强会一点字典树,也只会用数组来构建字典树(。・・)ノ


字典树,又叫前缀树,英文缩写是Trie,主要是因为其是一棵树,这可树根节点没有任何值,每一个子节点存储一个值(可以是字母,数字等),当遇到一些单词的前缀是一样时,这些单词会在同一条链上呈现,直到这些单词出现不同的值时。
先来一图,网上到处都是。
Trie(字典树)学习小结1_第1张图片

当我们在储存单词时,就这么储存。红点部分代表从这个点到根这一段形成了一个单词。这个有什么用呢?
比如现在trie里有一个单词abcd,现在查询是否有单词abc,如果没有红点的储存那么会被认为在Trie里出现过。就是这个作用- -|||。

代码实现:
一般用指针链表,又或者用数组。各有优劣,下次介绍。(有些神牛说用双数组,四数组什么的可以大大提高效率%%%%)


数组实现:用数组实现会浪费掉很多空间,但时间效率却是较高,这是典型的空间换时间的方法。

#include
#include
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)

using namespace std;

const int maxn=1e4;
struct trie{
    int next[26],end;//定义字典树,end表示改点是否为红点。
}tree[maxn];
int n,num; 
char s[10];

void add(char *s)//插入操作。
{
    int now=0, len=strlen(s);
    fo(i,0,len-1){
        int c=s[i]-'a';
        if (!tree[now].next[c]) tree[now].next[c]=num++;
        now=tree[now].next[c];
    }
    tree[now].end=1;
}
bool find(char *s)//查询操作。
{
    int now=0, len=strlen(s);
    fo(i,0,len-1){
        int c=s[i]-'a';
        if (!tree[now].next[c]) return false;
        now=tree[now].next[c];
    }
    if (tree[now].end) return true;//用红点判断是否构成单词。
    else return false;
}
int main()
{
    freopen("trie.in","r",stdin);
    scanf("%d",&n);
    num=1;
    fo(i,1,n){
        scanf("%s",&s);
        add(s);
    }
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%s",&s);
        if (find(s)) printf("YES\n");
        else printf("NO\n");
    }
    fclose(stdin);
}

蒻蒟一个,写的渣,求放过~~。
Trie(字典树)学习小结1_第2张图片

你可能感兴趣的:(信息技术,字典树)