『字典树』Trie字典树算法

学习Trie前提须知

(Trie)是一个字符串算法,它能够将很多个字符串映射在一棵树上,并且能够很快的判断一个串是否是另一个串的子串,也能够进行统计字符串出现次数等一些其他的东西,考题出现的频率不高,多作用于AC自动机的前置技能。 (甚至可以在Trie上DP)

算法内容

竞赛需要用到的点

1、(Trie)的结构体数组最好往大里开

2、(Trie)在字符串的题里受限都比较大,常与(kmp)混合用来进行AC自动机算法

Trie求字符串是否出现过略讲

(Trie)字典树,从名字就能看出是一棵树形结构了,每一个子树都是一个字符串或多个字符串。

(Trie)字典树与其他算法不同,直接从代码入手也许更好理解

将字符加入字典树

int tot;
void trieInsert(char *c, int rt) { //trieInsert(c, 0);
    int len = strlen(c);
    for (int i = 0; i < len; i++) {
        int id = c[i] - 'a';
        if(!trie[rt].son[id]) trie[rt].son[id] = ++tot;
        rt = trie[rt].son[id];
    } trie[rt].have = 1;
}

将字符串导入 (Trie) 中,从这个代码我们可以得到

  • 根节点为空节点,每个节点最多可以接26个点
  • 每个节点上代表为一个字符,末尾需要打上标记,不然若出现一个以当前字符为真前缀的字符就不好判断了

判断字符串是否存在

bool trieFind(char *c, int rt) {
    int len = strlen(c);
    for (int i = 0; i < len; i++) {
        int id = c[i] - 'a';
        if(!trie[rt].son[id]) return false;
        rt = trie[rt].son[id];
    }

    if(!trie[rt].have) return false;
}

思路和上面相同 并无多大改动

看一道模板题于是他错误的点名开始了

//#define fre yes

#include <cstdio>
#include <cstring>

const int N = 800005;
struct Node {
    int son[26];
    int cnt;
    bool have;
} trie[N];

int tot;
void trieInsert(char *c, int rt) {
    int len = strlen(c);
    for (int i = 0; i < len; i++) {
        int id = c[i] - 'a';
        if(!trie[rt].son[id]) trie[rt].son[id] = ++tot;
        rt = trie[rt].son[id];
    } trie[rt].have = 1;
}

int flag;
bool trieFind(char *c, int rt) {
    int len = strlen(c);
    for (int i = 0; i < len; i++) {
        int id = c[i] - 'a';
        if(!trie[rt].son[id]) return false;
        rt = trie[rt].son[id];
    }

    if(!trie[rt].have) return false;
    if(!trie[rt].cnt) {
        trie[rt].cnt++;
        return true;
    } else {
        flag = 1;
        return true;
    }
}

int main() {
    static int n, m;
    scanf("%d", &n);
    char c[105];
    for (int i = 1; i <= n; i++) {
        scanf("%s", c);
        trieInsert(c, 0);
    }

    scanf("%d", &m);
    for (int i = 1; i <= m; i++) {
        scanf("%s", c);
        if(trieFind(c, 0) && flag == 0) {
            puts("OK");
        } else if(trieFind(c, 0) && flag == 1) {
            flag = 0;
            puts("REPEAT");
        } else puts("WRONG");
    } return 0;
}

原文地址:https://www.cnblogs.com/Nicoppa/p/11508440.html