侧边栏壁纸
博主头像
GabrielxD

列車は必ず次の駅へ。では舞台は?私たちは?

  • 累计撰写 471 篇文章
  • 累计创建 108 个标签
  • 累计收到 9 条评论

目 录CONTENT

文章目录

【Trie树】Trie字符串统计「Trie树基础」

GabrielxD
2022-11-10 / 0 评论 / 0 点赞 / 16 阅读 / 871 字 / 正在检测是否收录...

题目

835. Trie字符串统计


维护一个字符串集合,支持两种操作:

  1. I x 向集合中插入一个字符串 xx
  2. Q x 询问一个字符串在集合中出现了多少次。

共有 NN 个操作,输入的字符串总长度不超过 10510^5,字符串仅包含小写英文字母。

输入格式

第一行包含整数 NN,表示操作数。

接下来 NN 行,每行包含一个操作指令,指令为 I xQ x 中的一种。

输出格式

对于每个询问指令 Q x,都要输出一个整数作为结果,表示 xx 在集合中出现的次数。

每个结果占一行。

数据范围

1N2×1041 \le N \le 2 \times 10^4

输入样例:

5
I abc
Q abc
Q ab
I ab
Q ab

输出样例:

1
0
1

解题

方法一:Trie 树

思路

Trie树模版:Trie 树

Trie 树

Trie 树是一种用于高效地存储和查找字符串集合的数据结构。

我们可以用数组来模拟树状结构:sons[][] 中存的是每个节点的子节点在 sons 中的下标,cnts 中存的是某个节点为结尾的数量,下标是 00 的点既表示根节点又表示空节点,idx数组模拟单链表中的 idx 相同也表示当前用到了哪个节点。

  • 插入操作:遍历字符串,维护一个指针(p)从根节点开始,如果子节点中不存在当前字符就创建一个新的节点,然后走到下一个节点,遍历完成后 p 会指向最后一个字符所在节点,把这个节点上的计数增加表示以该节点结尾的字符串数量增加。
  • 查询操作:遍历字符串,维护一个指针(p)从根节点开始,如果子节点中不存在当前字符说明树中不存在该字符串,直接返回 0,否则继续走到下一个节点,遍历完成后 p 会指向最后一个字符所在节点,返回该节点的数量(cnts[p])即可。

代码

#include <iostream>

using namespace std;

const int N = 1e5 + 10;
int sons[N][26], cnts[N], idx;
int n;

void insert(char word[]) {
    int p = 0;
    for (int i = 0; word[i]; ++i) {
        int curr = word[i] - 'a';
        if (!sons[p][curr]) sons[p][curr] = ++idx;
        p = sons[p][curr];
    }
    ++cnts[p];
}

int count(char word[]) {
    int p = 0;
    for (int i = 0; word[i]; ++i) {
        int curr = word[i] - 'a';
        if (!sons[p][curr]) return 0;
        p = sons[p][curr];
    }
    return cnts[p];
}

int main() {
    scanf("%d\n", &n);
    while (n--) {
        char ope, s[N];
        scanf("%c %s\n", &ope, s);
        if (ope == 'I') insert(s);
        else printf("%d\n", count(s));
    }
    
    return 0;
}
import java.util.*;
import java.io.*;

public class Main {
    static final int N = (int) 1e5 + 10;
    static int[][] sons = new int[N][26];
    static int[] cnts = new int[N];
    static int idx = 0;
    
    static void insert(String word) {
        int n = 0;
        for (char ch : word.toCharArray()) {
            int curr = ch - 'a';
            if (sons[n][curr] == 0) sons[n][curr] = ++idx;
            n = sons[n][curr];
        }
        ++cnts[n];
    }
    
    static int count(String word) {
        int n = 0;
        for (char ch : word.toCharArray()) {
            int curr = ch - 'a';
            if (sons[n][curr] == 0) return 0;
            n = sons[n][curr];
        }
        return cnts[n];
    }
    
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(in.readLine());
        while (n-- > 0) {
            String line = in.readLine();
            if (line.charAt(0) == 'I') insert(line.substring(2));
            else System.out.println(count(line.substring(2)));
        }
    }
}

0

评论区