题目传送门

一、什么是Trie树

使用多个字符串构建一个Trie树:
8个字符串:
\(abcdef\) \(abdef\) \(aced\) \(bcdf\) \(bcff\) \(cdaa\) \(abc\) \(bcdc\)

AcWing 835. Trie字符串统计

总结

  • \(son[N][26]\)来描述\(Trie\)树,第一维是构建\(Trie\)树的字符串个数乘以字符串的最大长度,第二维是指\(a\sim z\)共26种可能。
  • \(son[i][j]=k\)是指节点\(i\)通过\(j\)这条边(比如\(a\),就是\(j=0\),\(b\)就是\(j=1\)...),值\(k\)是指到达了哪个子节点。

二、Trie树的构建与分析

#include <bits/stdc++.h>

using namespace std;
const int N = 100010;
int trie[N][26];
int st[N];
int idx;

// 插入
void insert(string str) {
    int p = 0;
    for (int i = 0; i < str.size(); i++) {
        int u = str[i] - 'a';
        if (!trie[p][u]) trie[p][u] = ++idx;
        p = trie[p][u];
    }
    st[p]++;
}

/**
 测试用例:
 8
 abcdef
 abdef
 aced
 bcdf
 bcff
 cdaa
 abc
 bcdc
 */

int main() {
    int n;
    cin >> n;
    while (n--) {
        //输入的字符串
        string str;
        cin >> str;
        //插入到Trie树
        insert(str);
    }
    printf("节点个数:%d\n", idx);
    for (int i = 0; i <= idx; i++)
        for (int j = 0; j < 26; j++)
            if (trie[i][j])
                printf("节点%d-> %c边 -> 节点%d\n", i, 'a' + j, trie[i][j]);

    return 0;
}

三、本题答案

#include <bits/stdc++.h>

using namespace std;
const int N = 100010;
int trie[N][26];
int st[N];
int idx;

// 插入
void insert(string str) {
    int p = 0;
    //遍历每一个字符串中的字符
    for (int i = 0; i < str.size(); i++) {
        //要放str[i],转化为u,可以理解u也就是str[i],即要放入的字符是什么
        int u = str[i] - 'a';
        //如果这条路径不存在,需要创建出来,这个位置有一个节点被创建,节点号为++idx
        if (!trie[p][u]) trie[p][u] = ++idx;
        //如果路径不存在,现在已经创建出来了;就是现在不管以前是不是路径存在,
        //现在都有了这条路径,走进去,准备接收下一个字符
        p = trie[p][u];
    }
    //记录p为终点的字符个数,有时也写为st[p]=1
    st[p]++;
}

//Trie树查询
int query(string str) {
    int p = 0;
    for (int i = 0; i < str.size(); i++) {
        int u = str[i] - 'a';
        if (!trie[p][u]) return 0;//中间找不到结点就停止
        p = trie[p][u];//继续深入查找~
    }
    //以p为结尾的单词的个数
    return st[p];
}

int main() {
    //优化输入
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    while (n--) {
        char op;
        //输入的字符串
        string str;
        cin >> op >> str;
        //插入到Trie树
        if (op == 'I') insert(str);
            //表示x在集合中出现的次数
        else printf("%d\n", query(str));
    }
    return 0;
}

相关文章: