объяснение Java-реализации поразрядной сортировки

Я читаю и узнаю о реализации сортировки по основанию Java, как показано ниже. Было бы здорово, если бы кто-нибудь разъяснил логическое значение pointTo, index и globalPtr.

https://www.hackerrank.com/challenges/string-similarity/editorial

private void radixSort0() {
    globalPtr = 0;
    Arrays.fill(bucketHead, -1);
    Arrays.fill(next, -1);

    for (int i = 0; i < n; i++) {
        int value = nr0[index[i]];
        if (bucketHead[value] == -1) bucketHead[value] = bucketTail[value] = globalPtr;
        else bucketTail[value] = next[bucketTail[value]] = globalPtr;
        pointTo[globalPtr++] = index[i];
    }

    int ptr = 0;
    for (int i = 0; i < M; i++)
        for (int j = bucketHead[i]; j != -1; j = next[j])
            index[ptr++] = pointTo[j];
}

person Lin Ma    schedule 20.02.2016    source источник
comment
не публикуйте проблемы hackerrank для ответов, лучше попробуйте что-нибудь и опубликуйте свой код для некоторых модификаций. счастливое кодирование   -  person SmashCode    schedule 20.02.2016
comment
Никогда, никогда не имитируйте этот стиль в названии, (не)комментарии, коде, программе. Простая часть — это globalPtr: следующий индекс для выделения. Ссылка на hackerrank требует входа в систему — содержание такое же, как у lydxlx?   -  person greybeard    schedule 20.02.2016
comment
Спасибо, @greybeard, тогда каков логический смысл pointTo?   -  person Lin Ma    schedule 21.02.2016
comment
@greybeard, меня особенно смущает это утверждение, bucketTail[value] = next[bucketTail[value]] = globalPtr, почему мы не можем просто использовать bucketTail[value] = next[bucketTail[value]]=index[i], не видя слишком много значений globalPtr? Ваш совет приветствуется. Спасибо.   -  person Lin Ma    schedule 21.02.2016
comment
(Укажите ссылку на github уместно или нет.) Эта часть добавляется в конец односвязного списка с использованием дополнительного уровня (де)индексации. Я действительно не пытался выяснить, нужно ли это: многие вещи, используемые в radixSort0, предустановлены или используются снаружи. (Если бы это был близкий код lydxlx, globalPtr, pointTo, bucketHead, bucketTail и next могли бы также быть локальными для radixSort0&1.) Я был бы удивлен, если бы база для этого кода не была взята из учебника по алгоритмам.   -  person greybeard    schedule 21.02.2016
comment
Спасибо @greybeard, вот код, основанный на этом коде (hackerrank.com/challenges/string -сходство/редакция), было бы здорово, если бы вы помогли прокомментировать строку bucketTail[value] = next[bucketTail[value]] = globalPtr, почему мы не можем просто использовать bucketTail[value] = next[bucketTail[value]]=index[i], не видеть слишком много значений globalPtr? Спасибо.   -  person Lin Ma    schedule 21.02.2016
comment
@greybeard, спасибо за ответ, я неправильно понял ваш вопрос. Я просмотрел код по ссылке на github, и он такой же, как и то, что я публикую. Будем признательны, если вы прокомментируете, почему мы не можем просто использовать bucketTail[value] = next[bucketTail[value]]=index[i], а не использовать pointTo и globalPrt. Спасибо.   -  person Lin Ma    schedule 22.02.2016
comment
(Я немного подумаю над кодом, возможно, после ночного сна.)   -  person greybeard    schedule 22.02.2016


Ответы (2)


Эта radixSort0() не является полной сортировкой по основанию. Если ваша цель — узнать о сортировке по основанию, поищите в другом месте.
В обоих (ненужно дублированных) методах radixSort int[] next используется для создания односвязных списков — с использованием индексов вместо ссылок и -1 вместо нуля. (Вы не можете не просто установить next[some_index_depending_on value] в index[i] — тогда не будет списков.) int[] pointTo, вероятно, будет более описательно называться value. Думайте о next&value как о связанных списках, представленных в экземпляре с двумя элементами данных типа массив, в качестве альтернативы массиву экземпляров с членами next&value. globalPtr - это наименьший индекс, еще не выделенный в этом/этих массивах/ах.

(Кричащее отсутствие комментариев в последующем коде связано с тем, что я не понимаю, почему кто-то должен пытаться создать массив суффиксов, используя это, или какой вклад в эту цель вносят фрагменты кода: не стесняйтесь исправлять и исправлять.)
Даже не думая о тестировании, способ Java справиться с этим может быть

private void radixSortStep(int[]nr) {
    List<Integer> value[] = new List[M];
    for (int i = 0; i < value.length; i++)
        value[i] = new ArrayList<Integer>(0);

    for (int i: indexes)
        value[nr[i]].add(i);

    int ptr = 0;
    for (int i = 0; i < M; i++)
        for (int val: value[i])
            indexes[ptr++] = val;
}

(с небольшим размахиванием руками о M (установить n+1) и nr1 (инициализировать записи, не скопированные из ранга, в n, а не -1))

person greybeard    schedule 22.02.2016
comment
Спасибо greybeard, работаю над изучением вашего кода. Еще одна путаница с версией кода github, я просмотрел код по ссылке github, и будет признателен, если вы прокомментируете, почему мы не можем просто использовать bucketTail[value] = next[bucketTail[value]]=index[i] и полностью исключить использование pointTo и globalPrt. Я думал, что мы можем безопасно использовать index[i], кроме использования pointTo/globalPtr для другого уровня косвенности. Пожалуйста, поправьте меня, если я ошибаюсь. Спасибо. - person Lin Ma; 22.02.2016
comment
Я попробовал в скобках: next[] и bucketTail[] предназначены для инфраструктуры List, только pointTo[] содержит значения (индекса). - person greybeard; 22.02.2016
comment
Привет, седобородый, мне нравится твоя элегантная реализация! Согласен со всеми вашими комментариями, кроме этого, Нельзя просто так next[some_index_depending_on value] установить в index[i] - не было бы списков., предположим, мы делаем поразрядную сортировку по 21 и 31, а сейчас по единицам. 21 будет вставлено в ведро как голова и хвост, мы назначим его позицию (в данном случае 0) непосредственно BucketHead[1] и BucketTail[1], когда мы будем иметь дело с 31 (чья позиция равна 1, что является значением index[1]), мы должны иметь возможность присвоить его следующему из BucketTail, - person Lin Ma; 23.02.2016
comment
И переместите BucketTail на 31. В коде это bucketTail[value] = next[bucketTail[value]] = index[i] или 'next[bucketTail[value]] = index[i]' + bucketTail[value]=index[i], что делает 21 -> 31, а 31 - хвостом. Итак, я думаю, что безопасно не использовать pointTo и next. Другая причина, по которой я думаю, что безопасно не использовать pointTo и next, - это резервы сортировки по основанию LSD. В чем проблема в моем описании? Пожалуйста, не стесняйтесь исправлять меня. Спасибо. - person Lin Ma; 23.02.2016
comment
Порядок резервирования сортировки по основанию LSD см. в ответе rcgldr на stackoverflow.com/questions/35544353/ - person Lin Ma; 23.02.2016
comment
(забыл обратиться к @LinMa в моем предыдущем комментарии) Не совсем уверен, что понимаю, к чему вы клоните. Вы можете сохранить одно значение в bucketHead[value] и второе в buckettail[value], но куда деваться 3-му, 7-му, сотый? - person greybeard; 23.02.2016
comment
Привет, седобородый, я думаю, мы можем использовать next для отслеживания связанного списка. Мой вопрос не об использовании next, но я думаю, что использование pointTo и globalPtr бесполезно. В вашем коде вы их не используете, верно? :) Точнее, я думаю, что эта строка bucketTail[value] = next[bucketTail[value]] = globalPtr должна быть записана как bucketTail[value] = next[bucketTail[value]] = index[i], а эта строка index[ptr++] = pointTo[j] должна быть записана как index[ptr++] = j;, и это та же логика, что и ваш код. Я могу ошибаться, и, пожалуйста, не стесняйтесь меня поправлять. :) - person Lin Ma; 23.02.2016
comment
Также это потому, что ваш элегантный код заставляет меня думать, что использование дополнительного уровня ссылки (с использованием globalPtr и pointTo) бесполезно. В вашем примере вы просто используете val, что совпадает с index, верно? - person Lin Ma; 23.02.2016
comment
Спасибо за помощь, седобородый. Отметьте свой ответ как отвеченный. - person Lin Ma; 28.02.2016

import java.io.*;
import java.util.*;

public class St {
    public static int calculate(String s){
        char[]arr=s.toCharArray();
        int length=arr.length;
        int count=length;
        for(int i=1;i<length;i++){
            int len=length-i;
            int j=0;
            for(;j<len;j++)
                if(arr[j]!=arr[j+i]){
                    break;
                }
            count+=j;
        }
        return count;
    }
    public static void main(String[] args) {
        Scanner scanner = new Scanner( System.in );
        int n=scanner.nextInt();
        for(int i=0;i<n;i++){
            String s=scanner.next();
            System.out.println(calculate(s));
        }
    }
}

он почти прошел все тестовые случаи, кроме двух последних, из-за тайм-аута, надеюсь, моя работа поможет счастливому кодированию.

person SmashCode    schedule 20.02.2016
comment
Спасибо SmashCode, как ваш ответ связан с моим вопросом? :) - person Lin Ma; 20.02.2016
comment
будет кнопка добавления комментариев, если вы имеете в виду, как я сказал количество пройденных тестовых случаев, я тоже пользователь hackerrank. - person SmashCode; 20.02.2016
comment
Спасибо SmashCode, я думаю, что ваш код работает медленнее, чем SuffixArray? Ваш код работает O (n ^ 2)? - person Lin Ma; 21.02.2016
comment
Привет, SmashCode, в исходном коде, который я разместил, где меня особенно смущает это утверждение, bucketTail[value] = next[bucketTail[value]] = globalPtr, почему мы не можем просто использовать bucketTail[value] = next[bucketTail[value]]=index[i], не видя слишком много значений globalPtr? Ваш совет приветствуется. Спасибо. - person Lin Ma; 21.02.2016