Libraryless. Click here for Pure Java version (3229L/19K).
1 | // A = type of value in nodes. |
2 | // Can be case-sensitive or case-insensitive |
3 | // values can't be null |
4 | sclass StringTrie<A> { |
5 | A value; |
6 | TreeMap<S, StringTrie<A>> children; |
7 | |
8 | *() {} |
9 | *(A *value) {} |
10 | *(Iterable<S> strings) { addAll(strings, null); } // give all leaves null values |
11 | |
12 | void makeCaseInsensitive() { |
13 | children = asCIMap(children); |
14 | } |
15 | |
16 | bool isCaseInsensitive() { |
17 | ret isCIMap(children); |
18 | } |
19 | |
20 | void addAll(Iterable<S> strings, A value) { |
21 | fOr (S s : strings) |
22 | add(s, value); |
23 | } |
24 | |
25 | void put(S string, A value) { add(string, value); } |
26 | |
27 | void add(S string, A value) { |
28 | ifdef StringTrie_debug printFunctionCall("StringTrie add", string, value); endifdef |
29 | // case 1: empty string |
30 | if (empty(string)) ret with this.value = value; |
31 | |
32 | // case 2: some prefix of new string exists |
33 | S existingPrefix = longestLocalPrefix(string); |
34 | |
35 | ifdef StringTrie_debug print(+existingPrefix); endifdef |
36 | if (nempty(existingPrefix)) { |
37 | StringTrie<A> child = children.get(existingPrefix); |
38 | S substring = substring(string, l(existingPrefix)); |
39 | |
40 | // case 2a: new string is complete suffix of existing child |
41 | ifdef StringTrie_debug print(+child); endifdef |
42 | if (child != null) |
43 | ret with child.add(substring, value); |
44 | |
45 | // case 2b: make new branch |
46 | StringTrie<A> branch = newChild(null); |
47 | if (branch.children == null) branch.children = new TreeMap; |
48 | Map.Entry<S, StringTrie<A>> e = children.higherEntry(existingPrefix); |
49 | S key = e.getKey(); |
50 | child = e.getValue(); |
51 | children.remove(e.getKey()); |
52 | children.put(existingPrefix, branch); |
53 | branch.children.put(substring(key, l(existingPrefix)), child); |
54 | branch.children.put(substring, newChild(value)); |
55 | ret; |
56 | } |
57 | |
58 | // case 3: no existing prefix, just add new child |
59 | if (children == null) children = new TreeMap; |
60 | children.put(string, newChild(value)); |
61 | } |
62 | |
63 | // returns TreeMap or ciMap |
64 | Map<S, A> asMap() { |
65 | Map<S, A> map = isCaseInsensitive() ? ciMap() : new TreeMap; |
66 | new StringBuilder buf; |
67 | collectMap(buf, map); |
68 | ret map; |
69 | } |
70 | |
71 | private void collectMap(StringBuilder buf, Map<S, A> map) { |
72 | if (value != null) map.put(str(buf), value); |
73 | int n = l(buf); |
74 | for (S string, StringTrie<A> child : children) { |
75 | buf.append(string); |
76 | child.collectMap(buf, map); |
77 | buf.setLength(n); |
78 | } |
79 | } |
80 | |
81 | toString { |
82 | new StringBuilder buf; |
83 | if (value != null) { |
84 | buf.append("\"\" => ").append(value).append("\n"); |
85 | childrenToString(buf, 2); |
86 | } else |
87 | childrenToString(buf, 0); |
88 | ret str(buf); |
89 | } |
90 | |
91 | void toString(StringBuilder buf, int indent) { |
92 | if (value != null) |
93 | buf.append(" => ").append(value); |
94 | buf.append("\n"); |
95 | childrenToString(buf, indent+2); |
96 | } |
97 | |
98 | void childrenToString(StringBuilder buf, int indent) { |
99 | for (S string, StringTrie<A> child : children) { |
100 | buf.append(spaces(indent)).append(quote(string)); |
101 | child.toString(buf, indent); |
102 | } |
103 | } |
104 | |
105 | private StringTrie<A> newChild(A value) { |
106 | StringTrie<A> child = new(value); |
107 | if (isCaseInsensitive()) child.makeCaseInsensitive(); |
108 | ret child; |
109 | } |
110 | |
111 | S longestLocalPrefix(S string) { |
112 | ret isCaseInsensitive() |
113 | ? longestCommonPrefixOfCISetAndString(string, navigableKeys(children)) |
114 | : longestCommonPrefixOfNavigableSetAndString(string, navigableKeys(children)); |
115 | } |
116 | |
117 | Set<S> childStrings() { ret keys(children); } |
118 | StringTrie<A> getChild(S string) { ret children.get(string); } |
119 | NavigableMap<S, StringTrie<A>> children() { ret children; } |
120 | } |
download show line numbers debug dex old transpilations
Travelled to 5 computer(s): bhatertpkbcr, ekrmjmnbrukm, mqqgnosmbjvj, pyentgdyhuwx, vouqrxazstgt
No comments. add comment
Snippet ID: | #1030153 |
Snippet name: | StringTrie |
Eternal ID of this version: | #1030153/29 |
Text MD5: | 864525b0eaada21cee2cdf106462822a |
Transpilation MD5: | 785ea2d584e69ea9f47e69fc6380c13e |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2021-01-13 21:00:58 |
Source code size: | 3729 bytes / 120 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 287 / 633 |
Version history: | 28 change(s) |
Referenced in: | [show references] |