	public double getV(int index, State qj) {
		assert(index >= 1);
		assert(index-1 < outputSencence.size()); 
		double cachedValue = checkCache(index, qj); 
		if (cachedValue != -1)
			return cachedValue;
		if (index == 1) {
			double probability;
			probability = stateCollection.startState().nextStateProbability(qj);
			probability *= qj.wordEmittingProbability(new Word(outputSencence.get(0)));
			addToCache(index, qj, probability);
			return probability;			
		}
		double max = 0;
		for (State qi : stateCollection.states.values()) {
			double value;
			value = getV(index - 1, qj);
			value *= qi.nextStateProbability(qj);
			value *= qj.wordEmittingProbability(new Word(outputSencence.get(index - 1)));
			if (value > max) {
				max = value;
			}
		}
		addToCache(index, qj, max);
		return max;
	}

	public double getAlpha(int index, State qj) {
		assert(index >= 1);
		assert(index-1 < outputSencence.size()); 
		double cachedValue = checkCache(index, qj); 
		if (cachedValue != -1)
			return cachedValue;
		if (index == 1) {
			double probability;
			probability = stateCollection.startState().nextStateProbability(qj);
			probability *= qj.wordEmittingProbability(new Word(outputSencence.get(0)));
			addToCache(index, qj, probability);
			return probability;			
		}
		double sum = 0;
		for (State qi : stateCollection.states.values()) {
			double value;
			value = getAlpha(index - 1, qj);
			value *= qi.nextStateProbability(qj);
			value *= qj.wordEmittingProbability(new Word(outputSencence.get(index - 1)));
			sum += value;
		}
		addToCache(index, qj, sum);
		return sum;
	}
