A trie , который поддерживает порядок вставки, например, с помощью LinkedHashMap
, делает трюк.
Я взломал простой трюк, подобный этому:
import org.junit.Test;
import java.util.*;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
public class LinkedTrieTest {
@Test
public void testLinkedTrie() {
List<String> input = asList(
"dbc",
"eb",
"cd",
"edd",
"acb",
"ebc",
"dac",
"edb",
"cda"
);
List<String> expected = asList(
"dbc",
"dac",
"eb",
"ebc",
"edd",
"edb",
"cd",
"cda",
"acb"
);
assertEquals(expected, iterableToList(new LinkedTrie(input)));
}
private List<String> iterableToList(Iterable<String> t) {
List<String> result = new ArrayList<String>();
for (String s : t) {
result.add(s);
}
return result;
}
private class LinkedTrie implements Iterable<String> {
private Node root = new Node();
private LinkedTrie() {
}
private LinkedTrie(Iterable<String> strings) {
addAll(strings);
}
private void addAll(Iterable<String> strings) {
for (String string : strings) {
add(string);
}
}
public void add(String s) {
root.add(s);
}
@Override
public Iterator<String> iterator() {
return root.iterator();
}
private class Node {
private Map<Character, Node> nodes = new LinkedHashMap<Character, Node>();
private void add(String s) {
if (s.isEmpty()) {
nodes.put(null,null);
return;
}
Character c = s.charAt(0);
Node node = nodes.get(c);
if (null == node) {
node = new Node();
}
nodes.put(c, node);
node.add(s.substring(1));
}
private Iterator<String> iterator() {
return new TrieIterator();
}
private class TrieIterator implements Iterator<String> {
private Iterator<Map.Entry<Character,Node>> prefixesWithSuffixes = nodes.entrySet().iterator();
private Character currentPrefix;
private Iterator<String> suffixesForCurrentPrefix = Collections.<String>emptyList().iterator();
@Override
public boolean hasNext() {
return suffixesForCurrentPrefix.hasNext() || prefixesWithSuffixes.hasNext();
}
@Override
public String next() {
if (outOfSuffixesForCurrentPrefix()) {
if (outOfPrefixes()) {
throw new NoSuchElementException();
}
Map.Entry<Character, Node> prefixWithSuffixes = prefixesWithSuffixes.next();
currentPrefix = prefixWithSuffixes.getKey();
if (null == currentPrefix) {
return "";
}
suffixesForCurrentPrefix = prefixWithSuffixes.getValue().iterator();
}
return currentPrefix + suffixesForCurrentPrefix.next();
}
private boolean outOfPrefixes() {
return !prefixesWithSuffixes.hasNext();
}
private boolean outOfSuffixesForCurrentPrefix() {
return !suffixesForCurrentPrefix.hasNext();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
}
}
}