11package class044 ;
22
3- import java .util .HashMap ;
3+ // 用固定数组实现前缀树,空间使用是静态的,路径是数组结构
4+ // 测试链接 : https://www.nowcoder.com/practice/7f8a8553ddbf4eaab749ec988726702b
5+ // 请同学们务必参考如下代码中关于输入、输出的处理
6+ // 这是输入输出处理效率很高的写法
7+ // 提交以下的code,提交时请把类名改成"Main",可以直接通过
8+
9+ import java .io .BufferedReader ;
10+ import java .io .IOException ;
11+ import java .io .InputStreamReader ;
12+ import java .io .OutputStreamWriter ;
13+ import java .io .PrintWriter ;
14+ import java .util .Arrays ;
415
5- // 用类描述实现前缀树,路径是哈希表结构
6- // 测试链接 : https://leetcode.cn/problems/implement-trie-ii-prefix-tree/
716public class Code02_TrieTree {
817
9- class Trie {
18+ public static int MAXN = 150001 ;
1019
11- class TrieNode {
12- public int pass ;
13- public int end ;
14- HashMap <Integer , TrieNode > nexts ;
20+ public static int [][] tree = new int [MAXN ][26 ];
1521
16- public TrieNode () {
17- pass = 0 ;
18- end = 0 ;
19- nexts = new HashMap <>();
20- }
21- }
22+ public static int [] end = new int [MAXN ];
2223
23- private TrieNode root ;
24+ public static int [] pass = new int [MAXN ];
25+
26+ public static int cnt ;
27+
28+ public static void build () {
29+ cnt = 1 ;
30+ }
2431
25- public Trie () {
26- root = new TrieNode ();
32+ public static void insert (String word ) {
33+ int cur = 1 ;
34+ pass [cur ]++;
35+ for (int i = 0 , path ; i < word .length (); i ++) {
36+ path = word .charAt (i ) - 'a' ;
37+ if (tree [cur ][path ] == 0 ) {
38+ tree [cur ][path ] = ++cnt ;
39+ }
40+ cur = tree [cur ][path ];
41+ pass [cur ]++;
2742 }
43+ end [cur ]++;
44+ }
2845
29- public void insert (String word ) {
30- TrieNode node = root ;
31- node .pass ++;
32- for (int i = 0 , path ; i < word .length (); i ++) { // 从左往右遍历字符
33- path = word .charAt (i );
34- if (!node .nexts .containsKey (path )) {
35- node .nexts .put (path , new TrieNode ());
46+ public static void delete (String word ) {
47+ if (search (word )) {
48+ int cur = 1 ;
49+ for (int i = 0 , path ; i < word .length (); i ++) {
50+ path = word .charAt (i ) - 'a' ;
51+ if (--pass [tree [cur ][path ]] == 0 ) {
52+ tree [cur ][path ] = 0 ;
53+ return ;
3654 }
37- node = node .nexts .get (path );
38- node .pass ++;
55+ cur = tree [cur ][path ];
3956 }
40- node . end ++ ;
57+ end [ cur ]-- ;
4158 }
59+ }
4260
43- public void erase (String word ) {
44- if (countWordsEqualTo (word ) > 0 ) {
45- TrieNode node = root ;
46- TrieNode next ;
47- node .pass --;
48- for (int i = 0 , path ; i < word .length (); i ++) {
49- path = word .charAt (i );
50- next = node .nexts .get (path );
51- if (--next .pass == 0 ) {
52- node .nexts .remove (path );
53- return ;
54- }
55- node = next ;
56- }
57- node .end --;
61+ public static boolean search (String word ) {
62+ int cur = 1 ;
63+ for (int i = 0 , path ; i < word .length (); i ++) {
64+ path = word .charAt (i ) - 'a' ;
65+ if (tree [cur ][path ] == 0 ) {
66+ return false ;
5867 }
68+ cur = tree [cur ][path ];
5969 }
70+ return end [cur ] > 0 ;
71+ }
6072
61- public int countWordsEqualTo (String word ) {
62- TrieNode node = root ;
63- for (int i = 0 , path ; i < word .length (); i ++) {
64- path = word .charAt (i );
65- if (!node .nexts .containsKey (path )) {
66- return 0 ;
67- }
68- node = node .nexts .get (path );
73+ public static int prefixNumber (String pre ) {
74+ int cur = 1 ;
75+ for (int i = 0 , path ; i < pre .length (); i ++) {
76+ path = pre .charAt (i ) - 'a' ;
77+ if (tree [cur ][path ] == 0 ) {
78+ return 0 ;
6979 }
70- return node .end ;
80+ cur = tree [cur ][path ];
81+ }
82+ return pass [cur ];
83+ }
84+
85+ public static void clear () {
86+ for (int i = 1 ; i <= cnt ; i ++) {
87+ Arrays .fill (tree [i ], 0 );
88+ end [i ] = 0 ;
89+ pass [i ] = 0 ;
7190 }
91+ }
92+
93+ public static int m , op ;
7294
73- public int countWordsStartingWith (String pre ) {
74- TrieNode node = root ;
75- for (int i = 0 , path ; i < pre .length (); i ++) {
76- path = pre .charAt (i );
77- if (!node .nexts .containsKey (path )) {
78- return 0 ;
95+ public static String [] splits ;
96+
97+ public static void main (String [] args ) throws IOException {
98+ BufferedReader in = new BufferedReader (new InputStreamReader (System .in ));
99+ PrintWriter out = new PrintWriter (new OutputStreamWriter (System .out ));
100+ String line = null ;
101+ while ((line = in .readLine ()) != null ) {
102+ build ();
103+ m = Integer .valueOf (line );
104+ for (int i = 1 ; i <= m ; i ++) {
105+ splits = in .readLine ().split (" " );
106+ op = Integer .valueOf (splits [0 ]);
107+ if (op == 1 ) {
108+ insert (splits [1 ]);
109+ } else if (op == 2 ) {
110+ delete (splits [1 ]);
111+ } else if (op == 3 ) {
112+ out .println (search (splits [1 ]) ? "YES" : "NO" );
113+ } else if (op == 4 ) {
114+ out .println (prefixNumber (splits [1 ]));
79115 }
80- node = node .nexts .get (path );
81116 }
82- return node . pass ;
117+ clear () ;
83118 }
84-
119+ out .flush ();
120+ in .close ();
121+ out .close ();
85122 }
86123
87124}
0 commit comments