1、题目描述
维护一个字符串集合,支持两种操作:
- “I x”向集合中插入一个字符串x;
- “Q x”询问一个字符串在集合中出现了多少次。
共有N个操作,输入的字符串总长度不超过 105105,字符串仅包含小写英文字母。
输入格式
第一行包含整数N,表示操作数。
接下来N行,每行包含一个操作指令,指令为”I x”或”Q x”中的一种。
输出格式
对于每个询问指令”Q x”,都要输出一个整数作为结果,表示x在集合中出现的次数。
每个结果占一行。
数据范围
1≤N≤2∗1041≤N≤2∗104
输入样例:
5 I abc Q abc Q ab I ab Q ab
输出样例:
1 0 1
2、分析
3、代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int N = 100010;
static int[][] son = new int[N][26]; //保存Trie树每个结点的子节点,每个结点可以看成最多有26个子节点
static int[] cnt = new int[N]; //保存以某个字符结尾的字符串出现的次数
static int idx = 1; //当前用到哪个下标
public static void insert(String x){
int p = 0; //根节点
char[] char_arr = x.toCharArray();
for(char c : char_arr){
int i = c - 'a';
//son[p][i]表示以p为根节点的树的子树
if(son[p][i] == 0){ //p这个结点不存在i这个儿子,则创建
son[p][i] = idx ++;
}
p = son[p][i];
}
cnt[p] ++;
}
public static int query(String str){
int p = 0;
char[] char_arr = str.toCharArray();
for(char c : char_arr){
int i = c - 'a';
if(son[p][i] == 0){
return 0;
}
p = son[p][i];
}
return cnt[p];
}
public static void main(String[] args) throws Exception, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
while(n -- > 0){
String line = br.readLine();
String[] splits = line.split(" ");
if("I".equals(splits[0])){
insert(splits[1]);
}else{
int res = query(splits[1]);
System.out.println(res);
}
}
}
}
4、LeetCode 208. 实现 Trie (前缀树) Implement Trie (Prefix Tree)
https://leetcode-cn.com/problems/implement-trie-prefix-tree/
使用Trie的类结构体
public class Trie {
// 每个节点最多有26个不同的小写字母
private class TrieNode{
private boolean isEnd;
private TrieNode[] next;
public TrieNode(){
isEnd = false;
next = new TrieNode[26];
}
}
private TrieNode root;
public Trie(){
root = new TrieNode();
}
public void insert(String word){
TrieNode cur = root;
int len = word.length();
for(int i = 0;i < len;i ++){
int u = word.charAt(i) - 'a';
if(cur.next[u] == null){
cur.next[u] = new TrieNode();
}
cur = cur.next[u];
}
cur.isEnd = true; //加上一个标记,表示到结尾了,为一个单词
}
public boolean search(String word){
TrieNode cur = root;
int len = word.length();
for(int i = 0;i < len;i ++){
int u = word.charAt(i) - 'a';
if(cur.next[u] == null){
return false;
}
cur = cur.next[u];
}
return cur.isEnd;
}
public boolean startsWith(String prefix){
TrieNode cur = root;
int len = prefix.length();
for(int i = 0;i < len;i ++){
int u = prefix.charAt(i) - 'a';
if(cur.next[u] == null){
return false;
}
cur = cur.next[u];
}
return true; // 直接返回true
}
}