Acwing---835. Trie字符串统计

Trie字符串统计

  • 1.题目
  • 2.基本思想
  • 3.代码实现

1.题目

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

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

共有 N个操作,所有输入的字符串总长度不超过 1 0 5 10^5 105,字符串仅包含小写英文字母。

输入格式
第一行包含整数 N,表示操作数。

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

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

每个结果占一行。

数据范围
1 ≤ N ≤ 2 ∗ 1 0 4 1≤N≤2∗10^4 1N2104

输入样例:

5
I abc
Q abc
Q ab
I ab
Q ab

输出样例:

1
0
1

2.基本思想

Trie树中有个二维数组 son[N][26],表示当前结点的儿子,如果没有的话,可以等于++idx
Trie树本质上是一颗多叉树,对于字母而言最多有26个子结点。所以这个数组包含了两条信息。比如:son[1][0]=2表示1结点的一个值为a的子结点为结点2;如果son[1][0] = 0,则意味着没有值为a子结点。这里的son[N][26]相当于链表中的ne[N]。

void insert(char str[])
{
    int p = 0; //从根结点开始遍历
    for (int i = 0; str[i]; i ++ )
    {
        int u =str[i] - 'a';//将字母 转换到 对应的 0-25
        if (!son[p][u]) son[p][u] = ++ idx; //没有该子结点就创建一个
        p = son[p][u]; //走到p的子结点
    }

    cnt[p] ++; // cnt相当于链表中的e[idx]
}

3.代码实现

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;

public class _835Trie字符串统计 {
    static int N = 100010;
    static int[][] son = new int[N][26];
    static int idx;//id:当前用的的哪个下标,下标0:既是根节点又是空节点
    static int[] cnt = new int[N];//以当前这个点结尾的单词有多少个

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());//n次操作

        while (n-- > 0) {
            String[] s = br.readLine().split(" ");
            String opt = s[0], word = s[1];//opt:插入或删除  word:字符
            if (opt.equals("I")) insert(word);
            else if (opt.equals("Q")) query(word);
        }
    }

    private static void insert(String word) {
        int p = 0;//根节点是0
        for (int i = 0; i < word.length(); i++) {  //从根节点开始,从前向后遍历字符串
            int u = word.charAt(i) - 'a';//把当前这个字母对应的子节点编号搞出来
            if (son[p][u] == 0) son[p][u] = ++idx;//如果当前这个点上不存在对应的字母的话,创建出来
            p = son[p][u];//p指针下移
        }
        cnt[p]++;
    }

    private static void query(String word) {
        int p = 0;
        for (int i = 0; i < word.length(); i++) {
            int u = word.charAt(i) - 'a';//拿到对应
            if (son[p][u] == 0) {
                System.out.println(0);
                return;
            }
            p = son[p][u];//p指针下移
        }
        System.out.println(cnt[p]);
        return;
    }
}

你可能感兴趣的:(#,Acwing,刷题,java,算法,数据结构)