public NBestIterator(TagLattice<String> lattice,
                             int[] tokenStarts,
                             int[] tokenEnds,
                             int maxResults,
                             String beginTagPrefix,
                             String inTagPrefix,
                             String outTag) {
            mBeginTagPrefix = beginTagPrefix;
            mInTagPrefix = inTagPrefix;
            mOutTag = outTag;

            mLattice = lattice;
            mTokenStarts = tokenStarts;
            mTokenEnds = tokenEnds;
            mMaxResults = maxResults;
            Set<String> chunkTypeSet = new HashSet<String>();
            SymbolTable tagSymbolTable = lattice.tagSymbolTable();
            for (int k = 0; k < lattice.numTags(); ++k)
                if (lattice.tag(k).startsWith(mInTagPrefix))
                    chunkTypeSet.add(lattice.tag(k).substring(mInTagPrefix.length()));
            mChunkTypes = chunkTypeSet.toArray(Strings.EMPTY_STRING_ARRAY);
            mBeginTagIds = new int[mChunkTypes.length];
            mInTagIds = new int[mChunkTypes.length];
            for (int j = 0; j < mChunkTypes.length; ++j) {
                mBeginTagIds[j] = tagSymbolTable.symbolToID(mBeginTagPrefix + mChunkTypes[j]);
                mInTagIds[j] = tagSymbolTable.symbolToID(mInTagPrefix + mChunkTypes[j]);
            }
            mOutTagId = tagSymbolTable.symbolToID(mOutTag);

            mStateQueue = new BoundedPriorityQueue<NBestState>(ScoredObject.comparator(),
                                                               maxResults);
            mChunkQueue = new BoundedPriorityQueue<Chunk>(ScoredObject.comparator(),
                                                          maxResults);

            double[] nonContBuf = new double[lattice.numTags()-1];
            for (int j = 0; j < mChunkTypes.length; ++j) {
                int lastN = lattice.numTokens() - 1;
                if (lastN < 0) continue;
                String chunkType = mChunkTypes[j];
                int inTagId = mInTagIds[j];
                int beginTagId = mBeginTagIds[j];
                // System.out.println("beginTagId=" + beginTagId + " lastN=" + lastN);
                mChunkQueue.offer(ChunkFactory.createChunk(mTokenStarts[lastN],
                                                           mTokenEnds[lastN],
                                                           chunkType,
                                                           lattice.logProbability(lastN,beginTagId)));
                if (lastN > 0) {
                    mStateQueue.offer(new NBestState(lattice.logBackward(lastN,inTagId),
                                                     lastN,lastN,j));
                }
                for (int n = 0; n < lastN; ++n) {
                    double nonCont = nonContLogSumExp(j,n,beginTagId,lattice,nonContBuf);
                    mChunkQueue.offer(ChunkFactory.createChunk(mTokenStarts[n],
                                                               mTokenEnds[n],
                                                               chunkType,
                                                               nonCont + lattice.logForward(n,beginTagId)
                                                               - lattice.logZ()));
                }
                for (int n = 1; n < lastN; ++n) {
                    double nonCont = nonContLogSumExp(j,n,inTagId,lattice,nonContBuf);
                    mStateQueue.offer(new NBestState(nonCont,n,n,j));
                }
            }
        }