1 | /** |
2 | * A character tree map. |
3 | */ |
4 | static class Trie<T> { |
5 | private final char start; |
6 | private final Trie<T>[] arr; |
7 | public final T value; |
8 | |
9 | private Trie(char start, Trie<T>[] arr, @Nullable T value) { |
10 | this.start = start; |
11 | this.arr = arr; |
12 | this.value = value; |
13 | } |
14 | |
15 | @Nullable Trie<T> get(char ch) { |
16 | int i = ch - start; |
17 | return 0 <= i && i < arr.length ? arr[i] : null; |
18 | } |
19 | |
20 | @Nullable Trie<T> getIgnoreCase(char ch) { |
21 | int i = lower(ch) - start; |
22 | return 0 <= i && i < arr.length ? arr[i] : null; |
23 | } |
24 | |
25 | /** |
26 | * Returns the value corresponding to s[off:end]. |
27 | */ |
28 | @Nullable T get(String s, int off, int end) { |
29 | Trie<T> t = this; |
30 | while (off < end) { |
31 | t = t.get(s.charAt(off++)); |
32 | if (t == null) { return null; } |
33 | } |
34 | return t.value; |
35 | } |
36 | |
37 | @Nullable T get(char[] s, int off, int end) { |
38 | Trie<T> t = this; |
39 | while (off < end) { |
40 | t = t.get(s[off++]); |
41 | if (t == null) { return null; } |
42 | } |
43 | return t.value; |
44 | } |
45 | |
46 | /** |
47 | * Returns the value corresponding to s[off:end] ignoring the case of ASCII |
48 | * characters and matching only against lowercase keys. |
49 | */ |
50 | @Nullable T getIgnoreCase(String s, int off, int end) { |
51 | Trie<T> t = this; |
52 | while (off < end) { |
53 | t = t.getIgnoreCase(s.charAt(off++)); |
54 | if (t == null) { return null; } |
55 | } |
56 | return t.value; |
57 | } |
58 | |
59 | @Nullable T getIgnoreCase(char[] s, int off, int end) { |
60 | Trie<T> t = this; |
61 | while (off < end) { |
62 | t = t.getIgnoreCase(s[off++]); |
63 | if (t == null) { return null; } |
64 | } |
65 | return t.value; |
66 | } |
67 | |
68 | @Override |
69 | public String toString() { |
70 | StringBuilder sb = new StringBuilder(); |
71 | toString(sb, 0); |
72 | return sb.toString(); |
73 | } |
74 | |
75 | private void toString(StringBuilder sb, int depth) { |
76 | sb.append(value).append(" {"); |
77 | ++depth; |
78 | for (int i = 0; i < arr.length; ++i) { |
79 | if (arr[i] == null) { continue; } |
80 | sb.append('\n'); |
81 | for (int j = depth; --j >= 0;) { sb.append(" "); } |
82 | sb.append('\'').append((char) (i + start)).append("':"); |
83 | arr[i].toString(sb, depth); |
84 | } |
85 | sb.append("}"); |
86 | } |
87 | |
88 | static <A> Builder<A> builder() { return new Builder<A>(null, (char) 0); } |
89 | |
90 | static final class Builder<A> { |
91 | A value; |
92 | final char ch; |
93 | final List<Builder<A>> children = new ArrayList<Builder<A>>(); |
94 | |
95 | Builder(@Nullable A value, char ch) { |
96 | this.value = value; |
97 | this.ch = ch; |
98 | } |
99 | |
100 | Builder<A> put(String s, @Nullable A newValue) { |
101 | put(this, s, newValue); |
102 | return this; |
103 | } |
104 | |
105 | static <A> void put(Builder<A> b, String s, @Nullable A newValue) { |
106 | for (int i = 0, n = s.length(); i < n; ++i) { |
107 | char ch = s.charAt(i); |
108 | Builder<A> next = null; |
109 | for (Builder<A> child : b.children) { |
110 | if (child.ch == ch) { |
111 | next = child; |
112 | break; |
113 | } |
114 | } |
115 | if (next == null) { |
116 | next = new Builder<A>(null, ch); |
117 | b.children.add(next); |
118 | } |
119 | b = next; |
120 | } |
121 | b.value = newValue; |
122 | } |
123 | |
124 | @SuppressWarnings("unchecked") |
125 | Trie<A> build() { |
126 | Trie<A>[] arr; |
127 | int n = children.size(); |
128 | char min = 0; |
129 | if (n == 0) { |
130 | arr = (Trie<A>[]) NO_TRIES; |
131 | } else { |
132 | Collections.sort(children, new Comparator<Builder<?>>() { |
133 | public int compare(Builder<?> a, Builder<?> b) { |
134 | return a.ch - b.ch; |
135 | } |
136 | }); |
137 | min = children.get(0).ch; |
138 | int max = children.get(n-1).ch; |
139 | arr = (Trie<A>[]) new Trie<?>[max - min + 1]; |
140 | for (int i = 0; i < n; ++i) { |
141 | Builder<A> b = children.get(i); |
142 | arr[b.ch - min] = b.build(); |
143 | } |
144 | } |
145 | return new Trie<A>(min, arr, value); |
146 | } |
147 | } |
148 | |
149 | private static final Trie<?>[] NO_TRIES = new Trie<?>[0]; |
150 | } |
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: | 760 / 907 |
Version history: | 3 change(s) |
Referenced in: | [show references] |