public Trie optimize(Trie orig) {List<CharSequence> cmds = orig.cmds;List<Row> rows = new ArrayList<>();List<Row> orows = orig.rows;int remap[] = new int[orows.size()];for (int j = orows.size() - 1; j >= 0; j--) {Row now = new Remap(orows.get(j), remap);boolean merged = false;for (int i = 0; i < rows.size(); i++) {Row q = merge(now, rows.get(i));if (q != null) {rows.set(i, q);merged = true;remap[j] = i;break;}}if (merged == false) {remap[j] = rows.size();rows.add(now);}}int root = remap[orig.root];Arrays.fill(remap, -1);rows = removeGaps(root, rows, new ArrayList<Row>(), remap);return new Trie(orig.forward, remap[root], cmds, rows);}

public override Trie Optimize(Trie orig){IList<string> cmds = orig.cmds;IList<Row> rows = new List<Row>();IList<Row> orows = orig.rows;int[] remap = new int[orows.Count];for (int j = orows.Count - 1; j >= 0; j--){Row now = new Remap(orows[j], remap);bool merged = false;for (int i = 0; i < rows.Count; i++){Row q = Merge(now, rows[i]);if (q != null){rows[i] = q;merged = true;remap[j] = i;break;}}if (merged == false){remap[j] = rows.Count;rows.Add(now);}}int root = remap[orig.root];Arrays.Fill(remap, -1);rows = RemoveGaps(root, rows, new List<Row>(), remap);return new Trie(orig.forward, remap[root], cmds, rows);}
