// Copyright 2013 Thomas Müller // This file is part of MarMoT, which is licensed under GPLv3. package marmot.util; import java.io.Serializable; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class Trie<E extends Collectable> implements Serializable { private static final long serialVersionUID = 1L; private E content_; private Map<Character, Trie<E>> children_; public Trie() { children_ = null; content_ = null; } public Map<Character, Trie<E>> getChildren() { return children_; } public Trie<E> addWord(String word, E content) { return addWord(word, 0, content); } private Trie<E> addWord(String word, int index, E content) { if (index >= word.length()) { add(content); return this; } char c = word.charAt(index); if (children_ == null) { children_ = new HashMap<Character, Trie<E>>(); } Trie<E> trie = children_.get(c); if (trie == null) { trie = new Trie<E>(); children_.put(c, trie); } return trie.addWord(word, index + 1, content); } public Trie<E> getChild(char c) { if (children_ == null) { return null; } return children_.get(c); } public boolean isTerminal() { return content_ != null; } public E getContent() { return content_; } @Override public String toString() { return "Trie: " + content_ + " " + children_; } @SuppressWarnings("unchecked") public void add(E content) { if (content != null) { if (content_ == null) { content_ = (E) content.copy(); } else { content_.add(content); } } } public void propagateContent(int limit) { if (children_ != null) { for (Trie<E> child : children_.values()) { child.propagateContent(limit); add(child.content_); } if (content_ != null && (content_).sum() > limit) { content_ = null; } Iterator<Trie<E>> iterator = children_.values().iterator(); while (iterator.hasNext()) { Trie<E> child = iterator.next(); if (content_ != null) { if (content_.equals(child.content_)) { child.content_ = null; } } if (child.content_ == null && child.children_ == null) { iterator.remove(); } } if (children_.isEmpty()) { children_ = null; } } } public E getContent(String word) { return getContent(word, 0, content_); } public E getContent(String word, int index, E content) { if (index >= word.length()) { return content; } Trie<E> child = getChild(word.charAt(index)); if (child == null) { return content; } if (child.content_ != null) { content = child.content_; } return child.getContent(word, index + 1, content); } }