/*
* avenir: Predictive analytic based on Hadoop Map Reduce
* Author: Pranab Ghosh
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package org.avenir.markov;
import java.util.ArrayList;
import java.util.List;
/**
* Builds suffix tree
* @author pranab
*
*/
public class SuffixTreeNode {
private int count;
private String token;
private SuffixTreeNode parent;
private List<SuffixTreeNode> children = new ArrayList<SuffixTreeNode>();
/**
*
*/
public SuffixTreeNode() {
}
/**
* @param token
*/
public SuffixTreeNode(String token) {
this.token = token;
}
/**
* Adds a sequence of tokens.
* @param tokens
*/
public void add(List<String> tokens) {
add(tokens, 0);
}
/**
* Adds a sequence of tokens.
* @param tokens
* @param offset
*/
private void add(List<String> tokens, int offset) {
boolean done = false;
for (SuffixTreeNode node : children) {
if (node.token.equals(tokens.get(offset))) {
if (offset == tokens.size() - 1) {
incrementCounters(node);
done = true;
} else {
node.add(tokens, offset + 1);
}
}
}
//did not match with any child
if (!done) {
//create new child and navigate to new node
SuffixTreeNode newChild = new SuffixTreeNode(tokens.get(offset));
newChild.parent = this;
children.add(newChild);
if (offset == tokens.size() - 1) {
incrementCounters(newChild);
done = true;
} else {
newChild.add(tokens, offset + 1);
}
}
}
/**
* @param node
*/
private void incrementCounters(SuffixTreeNode node) {
SuffixTreeNode nextNode = node;
while(null != nextNode) {
++nextNode.count;
nextNode = nextNode.parent;
}
}
/**
* @param tokens
*/
public SuffixTreeNode find(List<String> tokens) {
return find(tokens, 0);
}
/**
* @param tokens
* @param offset
*/
public SuffixTreeNode find(List<String> tokens, int offset) {
boolean done = false;
SuffixTreeNode foundNode = null;
for (SuffixTreeNode node : children) {
if (node.token.equals(tokens.get(offset))) {
if (offset == tokens.size() - 1 ) {
if (node.isLeaf()) {
done = true;
foundNode = node;
}
break;
} else {
node.find(tokens, offset + 1);
}
}
}
return foundNode;
}
/**
* @return
*/
public boolean isRoot() {
return parent == null;
}
/**
* @return
*/
public boolean isLeaf() {
return children.isEmpty();
}
/**
* @return
*/
public int getCount() {
return count;
}
/**
* @return
*/
public String getToken() {
return token;
}
}