首页 > 其他 > 详细

trie字典树

时间:2019-07-19 21:41:57      阅读:136      评论:0      收藏:0      [点我收藏+]

一、引例

1、给出n个单词和m个询问,每次询问一个单词,回答这个单词是否在单词表中出现过。

2、给出n个单词和m个询问,每次询问一个字母序列,回答它是多少个单词的前缀。

设计自己的单词存储方式,实现插入、查询以下几个单词。

cat,cash,app,apple,aply,ok。

也许你的第一个想法是暴力搜索每一个单词,但是复杂度很很很很高啊

有一种东西叫做字典树,字典树的根节点连出来的每一条边存的就是出现的首字母,
然后但此后边的字母我们可以在后边存上, 这样每一个单词的最后一个单词就是最后存的
那条边,这样我们可以在那条代表着最后单词的边的下一个节点处打一个标记,然后表示一个单词就结束了;

like this
技术分享图片
把每一个单词放到字典树中...

二、基本操作

插入操作:

我们插入字符串的时候就每个边存一个字符,然后大概就是这个亚子:

技术分享图片

void add(string ch) {
    int len = ch.size(), root = 0, x;
    for (int i = 0; i < len; i++) {
        x = ch[i] - 'a';
        if (!trie[root][x]) trie[root][x] = ++tot;
        tr[trie[root][x]] = 1;
        root = trie[root][x];
    }
    tr[trie[root][x]] = 1;
}

修改操作:

应该都能看懂吧

int query(string ch) {
    int len = ch.size(), root = 0, ans = 0;
    int x;
    for (int i = 0; i < len; i++) {
        x = ch[i] - 'a';
        if (trie[root][x] == 0) return 0;
        ans = tr[trie[root][x]];
        tr[trie[root][x]] = 2;
        root = trie[root][x];
    }
    return ans;
}

三、练习

板子类

1.洛谷 P2580 于是他错误的点名开始了

大体思路:我们可以吧每一个人的名字一 一存入字典树中。然后查询操作的时候每查询一个单词

之后把每一个单词之后的节点都覆盖掉,然后下一次如果又有这个单词,那么就查不到了

上代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;
int tot, trie[400001][31], tr[400001];
string ch;

void add(string ch) {
    int len = ch.size(), root = 0, x;
    for (int i = 0; i < len; i++) {
        x = ch[i] - 'a';
        if (!trie[root][x]) trie[root][x] = ++tot;
        tr[trie[root][x]] = 1;
        root = trie[root][x];
    }
    tr[trie[root][x]] = 1;
}

int query(string ch) {
    int len = ch.size(), root = 0, ans = 0;
    int x;
    for (int i = 0; i < len; i++) {
        x = ch[i] - 'a';
        if (trie[root][x] == 0) return 0;
        ans = tr[trie[root][x]];
        tr[trie[root][x]] = 2;
        root = trie[root][x];
    }
    return ans;
}

int main() {
    int n, m;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        cin>>ch;
        add(ch);
    }
    scanf("%d", &m);
    for (int i = 1; i <= m; i++) {
        cin >> ch;
        if (query(ch) == 1) printf("OK\n");
        else if (query(ch) == 0) printf("WRONG\n");
        else if (query(ch) == 2) printf("REPEAT\n");
    }
}

字符串匹配类(往下我就不一 一讲了自己弄明白才是王道)

"strcmp()" Anyone?

异或类

C. Perfect Security

优化类

Remember the Word

还是看不懂的小伙伴们看这里
may be 这个比我都讲得好

trie字典树

原文:https://www.cnblogs.com/zzz-hhh/p/11215774.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!