/**
* A character tree map.
*/
static class Trie<T> {
private final char start;
private final Trie<T>[] arr;
public final T value;
private Trie(char start, Trie<T>[] arr, @Nullable T value) {
this.start = start;
this.arr = arr;
this.value = value;
}
@Nullable Trie<T> get(char ch) {
int i = ch - start;
return 0 <= i && i < arr.length ? arr[i] : null;
}
@Nullable Trie<T> getIgnoreCase(char ch) {
int i = lower(ch) - start;
return 0 <= i && i < arr.length ? arr[i] : null;
}
/**
* Returns the value corresponding to s[off:end].
*/
@Nullable T get(String s, int off, int end) {
Trie<T> t = this;
while (off < end) {
t = t.get(s.charAt(off++));
if (t == null) { return null; }
}
return t.value;
}
@Nullable T get(char[] s, int off, int end) {
Trie<T> t = this;
while (off < end) {
t = t.get(s[off++]);
if (t == null) { return null; }
}
return t.value;
}
/**
* Returns the value corresponding to s[off:end] ignoring the case of ASCII
* characters and matching only against lowercase keys.
*/
@Nullable T getIgnoreCase(String s, int off, int end) {
Trie<T> t = this;
while (off < end) {
t = t.getIgnoreCase(s.charAt(off++));
if (t == null) { return null; }
}
return t.value;
}
@Nullable T getIgnoreCase(char[] s, int off, int end) {
Trie<T> t = this;
while (off < end) {
t = t.getIgnoreCase(s[off++]);
if (t == null) { return null; }
}
return t.value;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
toString(sb, 0);
return sb.toString();
}
private void toString(StringBuilder sb, int depth) {
sb.append(value).append(" {");
++depth;
for (int i = 0; i < arr.length; ++i) {
if (arr[i] == null) { continue; }
sb.append('\n');
for (int j = depth; --j >= 0;) { sb.append(" "); }
sb.append('\'').append((char) (i + start)).append("':");
arr[i].toString(sb, depth);
}
sb.append("}");
}
static <A> Builder<A> builder() { return new Builder<A>(null, (char) 0); }
static final class Builder<A> {
A value;
final char ch;
final List<Builder<A>> children = new ArrayList<Builder<A>>();
Builder(@Nullable A value, char ch) {
this.value = value;
this.ch = ch;
}
Builder<A> put(String s, @Nullable A newValue) {
put(this, s, newValue);
return this;
}
static <A> void put(Builder<A> b, String s, @Nullable A newValue) {
for (int i = 0, n = s.length(); i < n; ++i) {
char ch = s.charAt(i);
Builder<A> next = null;
for (Builder<A> child : b.children) {
if (child.ch == ch) {
next = child;
break;
}
}
if (next == null) {
next = new Builder<A>(null, ch);
b.children.add(next);
}
b = next;
}
b.value = newValue;
}
@SuppressWarnings("unchecked")
Trie<A> build() {
Trie<A>[] arr;
int n = children.size();
char min = 0;
if (n == 0) {
arr = (Trie<A>[]) NO_TRIES;
} else {
Collections.sort(children, new Comparator<Builder<?>>() {
public int compare(Builder<?> a, Builder<?> b) {
return a.ch - b.ch;
}
});
min = children.get(0).ch;
int max = children.get(n-1).ch;
arr = (Trie<A>[]) new Trie<?>[max - min + 1];
for (int i = 0; i < n; ++i) {
Builder<A> b = children.get(i);
arr[b.ch - min] = b.build();
}
}
return new Trie<A>(min, arr, value);
}
}
private static final Trie<?>[] NO_TRIES = new Trie<?>[0];
}download show line numbers debug dex old transpilations
Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
| Snippet ID: | #1000859 |
| Snippet name: | Trie - too wasteful if you use unicode |
| Eternal ID of this version: | #1000859/4 |
| Text MD5: | 29bc95ab2f579b872419e09feec5db9d |
| Author: | stefan |
| Category: | javax |
| Type: | JavaX fragment (include) |
| Public (visible to everyone): | Yes |
| Archived (hidden from active list): | No |
| Created/modified: | 2018-04-20 16:13:34 |
| Source code size: | 3923 bytes / 150 lines |
| Pitched / IR pitched: | No / No |
| Views / Downloads: | 1227 / 1356 |
| Version history: | 3 change(s) |
| Referenced in: | [show references] |