import java.util.*;
//前缀树节点
class TrieNode {
TrieNode[] chs ;//保存子节点
int count ;//以该节点结尾的前缀 的单词数量
boolean isEnd ;//该节点是否为一个单词的结尾
String word ;//该节点若为一个单词的结尾,保存这个单词
TrieNode() {
this.chs = new TrieNode[26] ;//由于本题只涉及到26个小写字母,使用数组作为hash表(一般用Map)
this.count = 0 ;
this.isEnd = false ;
this.word = null ;
}
}
public class Solution {
/**
*
* @param operators string字符串二维数组 the ops
* @return string字符串一维数组
*/
private TrieNode root = new TrieNode() ;//根节点不代表任何字母,根节点的儿子节点代表 单词首字母
public String[] trieU (String[][] operators) {
List<String> list = new ArrayList<>() ;
for(String[] arr : operators) {
String opt = arr[0] ;
String word = arr[1] ;
switch(opt) {
case "1": insert(word) ; break ;
case "2": delete(word) ; break ;
case "3": list.add(search(word) == true ? "YES" : "NO") ;break ;
case "4": list.add(String.valueOf(prefixNumber(word))) ;break ;
}
}
String res[] = new String[list.size()] ;
return list.toArray(res) ;
}
public void insert(String word) {
char[] arr = word.toCharArray() ;
TrieNode cur = root ;
TrieNode chs1[] = cur.chs ;
for(int i = 0 ; i < arr.length ; i ++) {
if(chs1[arr[i]-'a'] == null) {
chs1[arr[i]-'a'] = new TrieNode() ;
chs1[arr[i]-'a'].count = 1 ;
} else {
chs1[arr[i]-'a'].count ++ ;
}
if(i == arr.length - 1) {
chs1[arr[i]-'a'].isEnd = true ;
chs1[arr[i]-'a'].word = word ;
} else {
chs1 = chs1[arr[i]-'a'].chs ;//向下层迭代
}
}
}
public void delete(String word) {
if(!search(word)) return ;
char[] arr = word.toCharArray() ;
TrieNode cur = root ;
TrieNode chs1[] = cur.chs ;
for(int i = 0 ; i < arr.length ; i ++) {
chs1[arr[i]-'a'].count -- ;
if(chs1[arr[i]-'a'].count == 0) {
chs1[arr[i]-'a'] = null ;
return ;
}
if(i == arr.length - 1) {
chs1[arr[i]-'a'].isEnd = false ;
chs1[arr[i]-'a'].word = null ;
} else {
chs1 = chs1[arr[i]-'a'].chs ;
}
}
}
public boolean search(String word) {
TrieNode cur = root ;
char[] arr = word.toCharArray() ;
TrieNode chs1[] = cur.chs ;
for(int i = 0 ; i < arr.length ; i ++) {
if(chs1[arr[i]-'a'] == null) return false ;
if(i == arr.length-1 && chs1[arr[i]-'a'].isEnd == true) return true ;
chs1 = chs1[arr[i]-'a'].chs ;
}
return false ;
}
public int prefixNumber(String pre) {
TrieNode cur = root ;
char[] arr = pre.toCharArray() ;
TrieNode chs1[] = cur.chs ;
for(int i = 0 ; i < arr.length ; i ++) {
if(chs1[arr[i]-'a'] == null) return 0 ;
if(i == arr.length - 1) return chs1[arr[i]-'a'].count ;
chs1 = chs1[arr[i]-'a'].chs ;
}
return 0 ;
}
}