Problem: AcWing 835. Trie字符串统计
文章目录
- 思路
- 解题方法
- 复杂度
- Code
思路
这是一个使用Trie树(字典树)解决的问题。Trie树是一种用于快速查询、插入和删除字符串的数据结构。在这个问题中,我们需要处理四种操作:插入字符串、查询字符串、查询前缀和删除字符串。这四种操作都可以通过Trie树来实现。
解题方法
插入字符串:
从根节点开始,按照字符串的每个字符,依次在Trie树中插入节点。同时,我们需要记录每个节点的pass和end值。pass表示有多少字符串经过这个节点,end表示有多少字符串以这个节点结束。
查询字符串:
从根节点开始,按照字符串的每个字符,依次在Trie树中查找节点。如果所有字符都找到对应的节点,并且最后一个字符对应的节点的end值大于0,那么说明这个字符串存在。
查询前缀:
从根节点开始,按照前缀的每个字符,依次在Trie树中查找节点。如果所有字符都找到对应的节点,那么最后一个字符对应的节点的pass值就是以这个前缀开头的字符串数量。
删除字符串:
首先,我们需要查询这个字符串是否存在。如果存在,那么我们就从根节点开始,按照字符串的每个字符,依次在Trie树中删除节点。删除节点时,我们需要更新pass和end值。
复杂度
时间复杂度:
对于每个操作,我们最多需要遍历字符串的所有字符,所以时间复杂度是 O ( n ) O(n) O(n),其中 n n n是字符串的长度。
空间复杂度:
我们需要存储所有的字符串,所以空间复杂度是 O ( m ) O(m) O(m),其中m是所有字符串的总长度。
Code
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Arrays;public class Main {static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));static int MAXN = (int) (2e5 + 10);static int[][] tree = new int[MAXN][60];static int[] pass = new int[MAXN];static int[] end = new int[MAXN];static int cnt = 1;static int n;public static void main(String[] args) throws NumberFormatException, IOException {clear();n = Integer.parseInt(in.readLine());while(n-- > 0) {String[] s = in.readLine().split(" ");if(s[0].equals("I")) {insert(s[1]);} else if(s[0].equals("Q")) {out.println(search(s[1]));}}out.flush();}private static void insert(String word) {int cur = 1;pass[cur]++;for (int i = 0, path; i < word.length(); i++) {path = word.charAt(i) - 'a';if (tree[cur][path] == 0) {tree[cur][path] = ++cnt;}cur = tree[cur][path];pass[cur]++;}end[cur]++;}private static int search(String word) {int cur = 1;for (int i = 0, path; i < word.length(); i++) {path = word.charAt(i) - 'a';if (tree[cur][path] == 0) {return 0;}cur = tree[cur][path];}return end[cur];}private static int prefixNumber(String pre) {int cur = 1;for (int i = 0, path; i < pre.length(); i++) {path = pre.charAt(i) - 'a';if (tree[cur][path] == 0) {return 0;}cur = tree[cur][path];}return pass[cur];}private static void delete(String word) {if (search(word) > 0) {int cur = 1;for (int i = 0, path; i < word.length(); i++) {path = word.charAt(i) - 'a';if (--pass[tree[cur][path]] == 0) {tree[cur][path] = 0;return;}cur = tree[cur][path];}end[cur]--;}}private static void clear() {// TODO Auto-generated method stubfor (int i = 0; i <= cnt; i++) {Arrays.fill(tree[i], 0);pass[i] = 0;end[i] = 0;}}}