Algorithm to find the smallest snippet from searching a document?

前端 未结 7 1430
太阳男子
太阳男子 2021-01-30 07:57

I\'ve been going through Skiena\'s excellent \"The Algorithm Design Manual\" and got hung up on one of the exercises.

The question is: \"Given a search string of three w

7条回答
  •  既然无缘
    2021-01-30 08:11

    Sample implementation in java (tested only with the implementation in the example, there might be bugs). The implementation is based on the replies above.

    import java.util.Arrays;
    
    
    public class SmallestSnippet {
        WordIndex[] words; //merged array of word occurences
    
        public enum Word {W1, W2, W3};
    
        public SmallestSnippet(Integer[] word1, Integer[] word2, Integer[] word3) {
            this.words = new WordIndex[word1.length + word2.length + word3.length];
            merge(word1, word2, word3);
            System.out.println(Arrays.toString(words));
        }
    
        private void merge(Integer[] word1, Integer[] word2, Integer[] word3) {
            int i1 = 0;
            int i2 = 0;
            int i3 = 0;
            int wordIdx = 0;
            while(i1 < word1.length || i2 < word2.length || i3 < word3.length) {
                WordIndex wordIndex = null;
                Word word = getMin(word1, i1, word2, i2, word3, i3);
                if (word == Word.W1) {
                    wordIndex = new WordIndex(word, word1[i1++]);
                }
                else if (word == Word.W2) {
                    wordIndex = new WordIndex(word, word2[i2++]);
                }
                else {
                    wordIndex = new WordIndex(word, word3[i3++]);
                }
                words[wordIdx++] = wordIndex;
            }       
        }
    
        //determine which word has the smallest index
        private Word getMin(Integer[] word1, int i1, Integer[] word2, int i2, Integer[] word3,
                int i3) {
            Word toReturn = Word.W1;
            if (i1 == word1.length || (i2 < word2.length && word2[i2] < word1[i1])) {
                toReturn  = Word.W2;
            }
            if (toReturn == Word.W1 && i3 < word3.length && word3[i3] < word1[i1])
            {
                toReturn = Word.W3;
            }
            else if (toReturn == Word.W2){
                if (i2 == word2.length || (i3 < word3.length && word3[i3] < word2[i2])) {
                    toReturn = Word.W3;
                }
            }
            return toReturn;
        }
    
        private Snippet calculate() {
            int start = 0;
            int end = 0;
            int max = words.length;
            Snippet minimum = new Snippet(words[0].getIndex(), words[max-1].getIndex());
            while (start < max)
            {
                end = start;
                boolean foundAll = false;
                boolean found[] = new boolean[Word.values().length];
                while (end < max && !foundAll) {
                    found[words[end].getWord().ordinal()] = true;
                    boolean complete = true;
                    for (int i=0 ; i < found.length && complete; i++) {
                        complete = found[i];
                    }
                    if (complete)
                    {
                        foundAll = true;
                    }
                    else {
                        if (words[end].getIndex()-words[start].getIndex() == minimum.getLength())
                        {
                            // we won't find a minimum no need to search further
                            break;
                        }
                        end++;
                    }
                }
                if (foundAll && words[end].getIndex()-words[start].getIndex() < minimum.getLength()) {
                    minimum.setEnd(words[end].getIndex());
                    minimum.setStart(words[start].getIndex());
                }
                start++;
            }
            return minimum;
    
        }
    
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            Integer[] word1 = {1,4,5};
            Integer[] word2 = {3,9,10};
            Integer[] word3 = {2,6,15};
            SmallestSnippet smallestSnippet = new SmallestSnippet(word1, word2, word3);
            Snippet snippet = smallestSnippet.calculate();
            System.out.println(snippet);
    
        }
    }
    

    Helper classes:

    public class Snippet {
    
        private int start;
    
        private int end;
    
    //getters, setters etc
    
        public int getLength()
        {
            return Math.abs(end - start);
        }
    }
    
    
    
    public class WordIndex
    {
        private SmallestSnippet.Word word;
        private int index;
        public WordIndex(SmallestSnippet.Word word, int index) {
    
            this.word = word;
            this.index = index;
        }
    }
    

提交回复
热议问题