Оптимизация преобразования Барроуза Уилера - PullRequest
1 голос
/ 14 мая 2011

Здравствуйте. У меня возникли некоторые трудности при оптимизации преобразования burrows * Wheeler . Я пытаюсь преобразовать текстовые файлы, однако преобразование больших текстовых файлов, таких как Библия, занимает слишком много времени.

Есть идеи, как поступить?

public BurrowsWheelerTransformEncoder()
{

}

private String originalSuffix(int index, String string)
{
    String temp = (string.substring(index,string.length()) + string.substring(0,index));

    //this bit just 'compresses' each transformation of text by producing
    //a prefix, so 'abracadabra' just becomes 'abrac'
    //this is so minimal amount of memory is used when it is stored in an array

    return temp.substring(0,5)+
    //the last character of the transformation is kept
           temp.charAt(temp.length()-1);
}

private String compressedSuffix(String string)
{
    //this method just 'compresses' original piece of text by producing
    //a prefix, so 'abracadabra' just becomes 'abrac'
    //this is so comprisons won't take so long
    return string.substring(0,5)+string.charAt(string.length()-1);
}

public static void main(String args[]) throws Exception
{
    BurrowsWheelerTransformEncoder encoder = new BurrowsWheelerTransformEncoder();
    BufferedReader input = new BufferedReader(new FileReader("src/compressionalgorithm/texts/manifesto.txt"));

    String text = "";
    //the row in the sorted array where the original text can be found
    int originalRow = 0;
    //system time when program began
    long startTime = System.nanoTime();

    //get text from file
    while(input.ready())
    {
        text += input.readLine();
    }
    //create a new array to hold all transformations
    String[] textArray = new String[text.length()];
    int length = text.length();

    //get individual transformations and put in array
    for(int i = 0; i < text.length(); i++)
    {
        textArray[i] = encoder.originalSuffix(i,text);
        //for debugging large text files, prints progress after every 10k'th 
        //transformation
        if(i%10000==0)
        System.out.println(i+"/"+length);
    }
    //uses java's internal methods to sort the array, presumably 
    //the most efficient way to do the sort (for now)
    Arrays.sort(textArray);

    String compressedOriginalText = encoder.compressedSuffix(text);

    //print the results
    for(int i = 0; i < textArray.length; i++)
    {
        if(textArray[i].equals(compressedOriginalText))
        {
            originalRow = i;
        }
        if(i%100==0)
        {
            System.out.println();
        }
        System.out.print(textArray[i].charAt(textArray[i].length()-1));
    }
    System.out.println("\nThe original transformation of the text was found at row " + originalRow + " of the sorted array.");
    System.out.println("Time elapsed: " + (System.nanoTime() - startTime));
 }

Ответы [ 2 ]

3 голосов
/ 08 ноября 2011

Для случая кодирования вам не нужно фактически создавать массив строк - используйте вместо этого массив int (или long в зависимости от размера вашего файла) для хранения индекса, с которого начинается вращающаяся строка.

  • Создание массива, инициализированного [0 1 2 3 ... n]
  • сортировка массива с помощью следующего сравнивать (предположим, compareTo() имеет доступ к исходной строке, original):

    int compareTo(int a, int b){
        int compare, len = original.length();
        do{
            char _a = original.charAt(a), _b = original.charAt(b);
            compare = _a-_b;
            a++; b++;
            if(a>=len)a-=len;
            if(b>=len)b-=len;
        }while(compare==0);
        return compare;
    }
    
  • запишите индекс «0» в массиве и добавьте его к своему выводу в качестве значения «start»

Для обращения, опять же, мы хотели бы избежать построения всей таблицы для текста размером с Библию.Мы можем сделать это, используя тот факт, что идентичные токены в первом и последнем рядах всегда находятся в одном и том же порядке.Это верно, потому что первая строка отсортирована и токены расположены циклически: для трех последовательных b в последнем ряду токены после них сортируются, поэтому b сортируются.Итак, для обратного:

  • отсортируйте выходные токены.Наряду с сохранением отсортированных токенов, сохраняйте индекс, с которого начинался каждый токен.Таким образом, для несортированных токенов «nbnaaa» вы должны хранить [3 4 5 2 0 1] и «aaabnn». Важно : вы ДОЛЖНЫ использовать стабильную сортировку для этого шага.
  • использовать значение "start", упомянутое ранее, для перестройки строки:

    string decode(string sorted, int[]index, int start){
        string answer = ""+sorted.charAt(start);
        int next = index[start];
        while(next!=start){
            answer = sorted.charAt(next) + answer;
            next = index[next];
        }
        return answer;
    }
    
1 голос
/ 14 мая 2011

Эта строка:

    String temp = (string.substring(index,string.length()) + string.substring(0,index));

собирается создавать копию всего входного текста каждый раз, когда вы его вызываете. Поскольку вы называете это N раз для входного текста из N символов, ваш алгоритм будет O(N^2).

Посмотрите, можете ли вы оптимизировать метод originalSuffix, чтобы избежать этого копирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...