package org.emdev.utils.collections;
import android.util.SparseArray;
public class SymbolTree<E> {
private final Node<E> root = new Node<E>();
public void add(final E value, final String s) {
add(value, s.toCharArray(), 0, s.length());
}
public void add(final E value, final char[] ch, final int start, final int length) {
Node<E> node = root;
for (int i = 0; i < length;) {
final char c = ch[start + i];
if (node.children == null) {
node.children = new SparseArray<SymbolTree.Node<E>>(8);
}
final Node<E> child = node.children.get(c);
if (child == null) {
final Node<E> term = new Node<E>();
term.ch = ch;
term.start = start + i + 1;
term.length = length - i - 1;
term.value = value;
node.children.append(c, term);
return;
}
if (child.length == 0) {
node = child;
i++;
continue;
}
final int tail = length - i - 1;
if (tail <= 0) {
final Node<E> inter = new Node<E>();
node.children.append(c, inter);
inter.children = new SparseArray<SymbolTree.Node<E>>(8);
inter.children.append(child.ch[child.start], child);
child.start += 1;
child.length -= 1;
inter.value = value;
return;
}
int pref = 0;
for (final int n = Math.min(child.length, tail); pref < n; pref++) {
if (child.ch[child.start + pref] != ch[start + i + 1 + pref]) {
break;
}
}
if (pref == child.length) {
node = child;
i += pref + 1;
continue;
} else if (pref > 0) {
final Node<E> inter = new Node<E>();
node.children.append(c, inter);
inter.ch = child.ch;
inter.start = child.start;
inter.length = pref;
inter.value = null;
inter.children = new SparseArray<SymbolTree.Node<E>>(8);
inter.children.append(child.ch[child.start + pref], child);
child.start += pref + 1;
child.length -= pref + 1;
if (tail == pref) {
inter.value = value;
return;
}
node = inter;
i += pref + 1;
continue;
} else {
final Node<E> inter = new Node<E>();
node.children.append(c, inter);
inter.children = new SparseArray<SymbolTree.Node<E>>(8);
inter.children.append(child.ch[child.start], child);
child.start += 1;
child.length -= 1;
node = inter;
i++;
continue;
}
}
}
public E get(final String s) {
return get(s.toCharArray(), 0, s.length());
}
public E get(final char[] ch, final int start, final int length) {
Node<E> node = root;
for (int i = 0; i < length;) {
if (node.children == null) {
return null;
}
final char c = ch[start + i];
final Node<E> child = node.children.get(c);
if (child == null) {
return null;
}
final int tail = length - i - 1;
if (child.length == 0) {
if (tail == 0) {
return child.value;
}
node = child;
i++;
continue;
}
if (child.length > tail) {
return null;
}
if (child.length <= tail) {
for (int ii = 0; ii < child.length; ii++) {
if (child.ch[ii + child.start] != ch[start + i + 1 + ii]) {
return null;
}
}
if (child.length == tail) {
return child.value;
}
i += 1 + child.length;
}
node = child;
}
return null;
}
private static class Node<E> {
char[] ch;
int start;
int length;
E value;
SparseArray<SymbolTree.Node<E>> children;
Node() {
}
@Override
public String toString() {
final StringBuilder buf = new StringBuilder("<");
if (length > 0) {
for (int i = 0; i < length; i++) {
buf.append(ch[start + i]);
}
}
buf.append(":");
buf.append(value);
buf.append(":");
buf.append(children);
return buf.append(">").toString();
}
}
public void clear() {
// TODO Auto-generated method stub
}
}