@SuppressWarnings("unchecked")
    @Override
    public String split(String word) {
        word = word+EOW;
        Value<State>[] alpha = new Value[2];
        HashMap<State, String>[] split = new HashMap[2];
        alpha[0] = initial(1.0);
        split[0] = new HashMap<State, String>();
        split[0].put(I, "");
        for (int t = 0; t < word.length(); ++t) {
            Character c = word.charAt(t);
            alpha[1 - t % 2] = new Value<State>();
            split[1 - t % 2] = new HashMap<State, String>();
            for (State q : alpha[t % 2].keySet()) {
                if (q.allows(c)) {
                    String s = split[t % 2].get(q);
                    double val = alpha[t % 2].getValue(q);
                    State next = q.next(c);
                    if (next != null) {
                        alpha[1 - t % 2].setValue(next, val * q.prNext(c));
                        split[1 - t % 2].put(next, s + c);
                    }
                    if (val * q.prRestart(c) > alpha[1 - t % 2].getValue(I)) {
                        alpha[1 - t % 2].setValue(I, val * q.prRestart(c));
                        if (t + 2 < word.length()) {
                            split[1 - t % 2].put(I, s + c + "-");
                        } else {
                            split[1 - t % 2].put(I, s + c);
                        }
                    }
                } else {
                    if(q==I) {
                        String s = split[t % 2].get(q);
                        double val = alpha[t % 2].getValue(q);
                        if (val * EPSILON > alpha[1 - t % 2].getValue(I)) {
                            alpha[1 - t % 2].setValue(I, val * EPSILON);
                            if (t + 2 < word.length()) {
                                split[1 - t % 2].put(I, s + c + "-");
                            } else {
                                split[1 - t % 2].put(I, s + c);
                            }
                        }
                    }
                }
            }
        }
        return BOW+split[word.length() % 2].get(I);
    }