-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTrie.java
More file actions
174 lines (141 loc) · 4.9 KB
/
Trie.java
File metadata and controls
174 lines (141 loc) · 4.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import java.util.ArrayList;
import java.util.List;
public class Trie {
private static class NoTrie {
NoTrie[] filhos;
boolean fim_palavra;
NoTrie(){
this.filhos = new NoTrie[26];
this.fim_palavra = false;
}
}
private final NoTrie raiz;
public Trie(){
this.raiz = new NoTrie();
}
public void insert(String palavra){
if(palavra == null){
return;
}
NoTrie atual = raiz;
for(int i = 0; i < palavra.length(); i++){
char c = palavra.charAt(i);
int idx = c - 'a';
if(idx < 0 || idx >= 26){
continue; // assume entrada já normalizada
}
if(atual.filhos[idx] == null){
atual.filhos[idx] = new NoTrie();
}
atual = atual.filhos[idx];
}
atual.fim_palavra = true;
}
// AUTO-COMPLETE
// 1) Localiza o nó correspondente ao prefixo
private NoTrie buscarNo(String prefixo){
if(prefixo == null){
return null;
}
NoTrie atual = raiz;
for(int i = 0; i < prefixo.length(); i++){
char c = prefixo.charAt(i);
int idx = c - 'a';
if(idx < 0 || idx >= 26){
return null; // prefixo inválido
}
if(atual.filhos[idx] == null){
return null; // prefixo inexistente
}
atual = atual.filhos[idx];
}
return atual;
}
// 2) Retorna sugestões para o prefixo (com limite de resultados)
public List<String> autocomplete(String prefixo, int limite){
List<String> sugestoes = new ArrayList<>();
if(prefixo == null){
return sugestoes;
}
if(limite <= 0){
return sugestoes;
}
// assume prefixo já normalizado (a-z)
NoTrie noPrefixo = buscarNo(prefixo);
if(noPrefixo == null){
return sugestoes; // prefixo inexistente -> sem sugestões
}
StringBuilder atual = new StringBuilder(prefixo);
dfsColetar(noPrefixo, atual, sugestoes, limite);
return sugestoes;
}
public void imprimirSubarvore(String prefixo, int limite){
if(prefixo == null){
System.out.println("(prefixo null)");
return;
}
if(limite <= 0){
System.out.println("(limite invalido)");
return;
}
NoTrie no = buscarNo(prefixo);
if(no == null){
System.out.println("Prefixo \"" + prefixo + "\" nao existe na Trie.");
return;
}
System.out.println("Subarvore do prefixo: \"" + prefixo + "\"");
System.out.println(prefixo + (no.fim_palavra ? " [PALAVRA]" : ""));
StringBuilder sb = new StringBuilder(prefixo);
imprimirRec(no, sb, 0, limite, new int[]{0});
}
private void imprimirRec(NoTrie no, StringBuilder atual, int nivel, int limite, int[] cont){
if(cont[0] >= limite){
return;
}
for(int i = 0; i < 26; i++){
if(no.filhos[i] != null){
atual.append((char)('a' + i));
// indentação
for(int k = 0; k < nivel + 1; k++){
System.out.print(" ");
}
// imprime o "ramo" atual
System.out.print("└─ " + (char)('a' + i));
if(no.filhos[i].fim_palavra){
System.out.print(" -> " + atual.toString() + " [PALAVRA]");
cont[0]++;
}
System.out.println();
imprimirRec(no.filhos[i], atual, nivel + 1, limite, cont);
atual.deleteCharAt(atual.length() - 1);
if(cont[0] >= limite){
return;
}
}
}
}
// 3) DFS para coletar palavras abaixo do nó do prefixo
private void dfsColetar(NoTrie no, StringBuilder atual, List<String> out, int limite){
if(out.size() >= limite){
return;
}
// Se esse nó marca fim de palavra, adiciona a palavra atual
if(no.fim_palavra){
out.add(atual.toString());
if(out.size() >= limite){
return;
}
}
// Percorre filhos em ordem (a..z) para sugestões ordenadas
for(int i = 0; i < 26; i++){
if(no.filhos[i] != null){
atual.append((char)('a' + i));
dfsColetar(no.filhos[i], atual, out, limite);
atual.deleteCharAt(atual.length() - 1); // backtrack
if(out.size() >= limite){
return;
}
}
}
}
}