PHP: array_key_exists ищет быстрее чем in_array в 500 раз

В 2014 уже писали про обыск массива, но вряд ли кто понял.

C тех пор вышло много версий PHP и не исправили значит обратная связь плохая и об этом мало кто знает. На питоне так же, и в 3* хуже чем в 2.7.

Иногда нужно найти строку в массиве строк — очень частая операция в разных алгоритмах и если массив небольшой и искать немного и не в цикле, то in_array нормально, на общую скорость не влияет, но если big data и искать надо массиве из миллиарда строк и миллиард раз, то это уже критично: лучше час вместо недели.

Простой тест показывает:

in_array ищет за 6-9 сек ideone.com/Yb1mDa 6600ms
а array_key_exists ищет тоже самое, но быстрее в 250(php5.6/py3.*) в 400+ раз (php7.3/py2.7) ideone.com/gwSmFc (цикл увеличен в 100 раз) 12ms (6600/12=550раз +-10% разброс из-за нагрузки и кеша)

Почему же такое происходит? Рассмотрим подробно:

1) Поиск строк на чистом ассемблере/си это сортировка массива строк (быстрая или пузырьковая), затем бинарный поиск.

Число шагов в бинарном поиске log(n) раз и зависит от размера массива, и намного меньше чем простой перебор.

Отсортировать массив строк можно заранее, один раз и закешировать, а потом делать миллиард поисков. Но это не помогает.

По умолчанию сортировка происходит каждый раз снова, хотя писали что улучшили в 7.2 in_array через хеш, но немного.

2) Поиск индекса/key(как строки) в ассоц. массиве/словаре происходит по хешу строк и обработкой коллизий.(ошибок поиска по хешу). Хеш это числовой индекс массива и выборка из него как (адрес нулевого элемента) + смещение * размер указателя на массив строк с этим хешем) в 2 шага. +перебор коллизий, шагов в среднем меньше бинарного поиска.
Хеш индекса делается автоматически заранее один раз при создании элемента словаря $m[key]=val и кешируется.

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

Дальше можно не читать, меняйте in_array на array_combine + array_key_exists и всё.

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

Для уменьшения коллизий можно выделить больше памяти, если возможно, что сейчас не такая проблема, как 50 лет назад когда 1 кб памяти на магн.катушках стоил как самолет. А именно тогда были придуманы все основные алгоритмы: sort/zip/gif/jpg/итд — им не надо много памяти, но они плохие, сейчас есть намного лучше, но им надо много памяти 1-16 Мб. Да, есть серверы с 256 Мб и на каждого отдельный поток и 16 Мб уже много, но на девайсе среднего юзера 1 Гб как минимум и 16 Мб это капля в море.

Еще больший эффект можно получить если заменить вызов функции array_key_exists на конструкцию isset($m[key]), она не чистит очередь команд и кеш, не использует стек и быстрее где-то на 20%.

Так же можно еще ускорить если создать массив 2х первых букв- 4*16кб и искать сначала по смещению (индекс=код 1го символа + 2го*256) указатель на массив хешей для остальной части строки, затем ищем уже среди маленького массива «хвостов» строк и коллизий на порядок меньше.

Это требует еще больше памяти и алгоритм сложнее, но поиск быстрее в 30+ раз. Но в пхп это не реализовано, можно написать свою библиотеку so/dll и вызывать, или попросить разработчиков добавить в 7.5.

Можно искать через mySQL, но надо группировать запросы и это будет все равно медленней.

P.S.: Этот способ нашел случайно методом тыка, интуиции и опыта когда ускорял один большой медленный сайт, таких тонкостей и приемов очень много, удалось добиться выгрузки данных в ексель с 40 сек до 0,8 сек, вывод списков с сортировкой и фильтрами и многих других вещей где стандартные приемы, либы и фреймворки делают это все слишком медленно, хотя конечно они удобны и разработку ускоряют.
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 50

    +5
    Дальше можно не читать, меняйте in_array на array_combine + array_key_exists и всё.

    А вы время array_combine учитываете?


    (но вообще, конечно, удивительно, что кому-то надо рассказывать про уместность применения хэш-таблиц...)

      –6
      В статье код теста есть и видно что array_combine или array_flip делается один раз! чтобы значения превратить в ключи и сделать массив уникальным это 0,1мс- (можно там же проверить). а дальше поиск 10000 раз -он для подсчета скорости алгоритма и в реальной жизни поможет если искать много, а если мало то без разницы. В массиве 100 строк через in_array искать удобней.

      А насчет хеш, некоторые даже не знают что это такое, разработчики PHP/Python видимо не в курсе что текущий алгоритм слабоват, а здесь мы превращаем большой массив строк в маленький массив их хешей как чисел 8,16,24,32 битных и число сравнений строк уменьшается в 256, 16к, итд раз. Алгоритм хеширования тоже влияет. Например надо в массиве из 2048 строк сделать 256 хешей- тогда в среднем надо не 1024 сравнения а 2048/256=8. перебор это 4 шага если равномерно, меньше если наиболее частые поместить в начало, или отсортировать 1 раз, а затем бинарный поиск, для массива 8 строк это 3 шага. Но если хеширование плохое — например КС % 256 то будет не 8, а где-то 2 где-то 16. А если будет сложное, то его считать долго. Но хеш считается один раз в длинном цикле и это намного меньше чем пузырьковая сортировка — там цикл n*n/2 и бинарный поиск требует больше шагов чем по индексу найти и сделать поиск в массиве который меньше в 256^n раз. где n-кол-во байт на хеш.
        +7
        В статье код теста есть и видно что array_combine или array_flip делается один раз!

        … и это неправильно, потому что это делает заголовок бессмысленным. Без сравнения времени array_combine вы сравниваете поиск перебором в массиве с поиском в хэш-таблице, и это простая и известная вещь: O(n) против O(1). Собственно, весь ваш заголовок к этому сводится: поиск в хэш-таблице (точный) быстрее, чем в массиве. Ну… да? Это, типа, азы алгоритмов, и именно с точки зрения отличия структур это и надо обсуждать.


        разработчики PHP/Python видимо не в курсе что текущий алгоритм слабоват

        … какой "текущий алгоритм" в Питоне слабоват?


        а здесь мы превращаем большой массив строк в маленький массив их хешей

        И это операция O(n).


        Если поиск надо делать много раз по одному и тому же массиву, сделать хэш-таблицу выгодно. Если поиск надо сделать один раз — невыгодно.

          –2
          1. идем сюда ideone.com/Yb1mDa — общее время 0.68s, только поиск 0.66s
          2. идем сюда ideone.com/gwSmFc — общее время 0.14s, только поиск 0.12s
          во втором поисков больше в 100 раз. считаем. 6800/14=? в каком месте неправильно? за что там +6, а мне -5? Вы хоть в школе учились? или это боты?
          Заголовок про поиск в массиве через in_array() — это проверка есть/нет а не позиции в массиве. Это очень сложно понять?

          Про текущий алгоритм отвечу когда мне +100 поставят, за попытку поделится с адекватными думающими людьми рабочим способом-костылем, исправляющим косяки разрабов, а не ерундой никому не нужной.
            +1
            во втором поисков больше в 100 раз. считаем. 6800/14=? в каком месте неправильно?

            В том, где вы делаете array_combine один раз. Повторюсь еще раз: если у вас есть на входе произвольный массив (именно массив, не ассоциативный массив), и вам надо найти в нем значение, один раз, поиск перебором (in_array) должен быть быстрее, чем сворачивание в хэш-таблицу и поиск на вхождение в ней (array_combine + array_key_exists).


            а что там +6, а мне -5?

            Да вот за это, в общем-то:


            Вы хоть в школе учились?

            .


            Заголовок про поиск в массиве через in_array() — это проверка есть/нет а не позиции в массиве. Это очень сложно понять?

            А при чем тут вообще позиция в массиве?


            Про текущий алгоритм отвечу когда мне +100 поставят,

            Ну то есть никогда. Дело ваше, но до тех пор ваше утверждение "текущий алгоритм в Python слабоват" безосновательно.

      +1

      https://github.com/php/php-src/pull/3360
      информация про isset/array_key_exists cскорее сего устаревшая (лень проверять).

        0
        а плюс за что? за лень проверять? ну так сходи и проверь, я проверил. в разных версиях пхп эффект разный и в 500 раз или в 510 раз -не так важно.
          0
          а плюс за что? за лень проверять?

          Ахаха, а за 2 минуты до этого ты пишешь:


          Про текущий алгоритм отвечу когда мне +100 поставят, за попытку поделится с адекватными думающими людьми рабочим способом-костылем, исправляющим косяки разрабов, а не ерундой никому не нужной.

          Вас там двое за одним аккаунтом?

        +6
        Не надо сравнивать поиск в массиве по значению и по ключу. Нет никакого сюрприза в том, что поиск по значению (который последовательно перебирает все значения) оказывается медленнее чем поиск по ключу (который оказывается хеш таблицей). Соответственно «500 раз» будет тем больше, чем больше элементов в массиве.
          –3
          Да, все правильно, в небольших массивах разницы почти нет, а в очень больших есть, но надо больше памяти на хеш и массив хешей, я думал если в in_array бинарный поиск, то сортировка заранее может поможет и сделать уникальным массив — нет, не помогает, так же долго. Видимо сортирует каждый раз или хеш считает. А с ключами-индексами один раз и кешируется всё. Можно код посмотреть, он открыт. А почему это не сделано в in_array и в питоне. Вот вопрос. Поиск в массиве очень частая и нужная операция. Но все юзают медленный способ, так как быстрый не знают и не узнают. Статья ушла в минус. Наверно люди думают что это ерунда и бред. Кстати за за статью об «обыске массиве» 6 лет назад, ни одного минуса, а там про тоже самое почти но менее подробно, а заголовок неудачный — я бы даже читать не стал.
            +2

            Почему-почему… Да потому что если это сделать — это нужно будет поддерживать при каждом изменении массива. А это уже приведет к замедлению в других местах.


            Это ваша задача как программиста — помнить о времени работы разных функций и выбирать правильные.

              –1
              Не надо ля-ля, добавить значение в индекс не дольше чем в массив, а исправить можно так — делаем копию массива и хешей в первый раз и кешируем.
              in_array это как раз та самая «правильная» ф-я которую надо использовать при поиске, а за костыль этот могут уволить или минусов наставить, людям не надо быстро — им надо понятно. А этот способ он не для всех, а кто шарит.
              0
              Поиск в массиве очень частая и нужная операция. Но все юзают медленный способ, так как быстрый не знают и не узнают.

              Потому что самый быстрый способ искать в массиве (в общем случае) — это перебор. O(n).


              А вот то, что кто-то не знает, что иногда надо использовать не массив, а другую структуру данных — это печально, да.

                –3
                перебор? смешно, ну так и ищете перебором месяц, а мы будем за час искать через хеш или бинарный поиск — зависит от размера и памяти. Выше объяснил, кто не понял — гугл в помощь.
                  +3
                  перебор? смешно

                  Очень смешно, да. Приведите способ, который будет быстрее в общем случае (то есть для любого массива), учитывая, что


                  через хеш

                  Требует создания хэш-таблицы, а это само по себе O(n).


                  бинарный поиск

                  Требует сортированного массива, а это O(n) в лучшем случае и O(n log n) в среднем. Плюс O(log n) на сам поиск, конечно.

                0
                А почему это не сделано в in_array и в питоне. Вот вопрос.

                Потому что не нужно это. Ну то есть в Питоне точно не нужно.

              0
              Комбинация «array_combine + array_key_exists» ломается сразу как только в массиве появляются одинаковые значения. Причем об этом говориться в первом же комментарии официальной документации array_combine.
              Это не помешает определить есть ли строка в массиве, но вот найти её индекс или количество строк уже проблема.

              И почему не использовать array_flip вместо array_combine? Подозреваю быстрей будет.

              Такое себе решение, вы сравниваете две совершенно разные функции.
                +1
                $m=array_combine($m,$m) делает массив уникальным без лишних вопросов.
                array_flip меняет местами ключи и значения. на повторы и пусто не проверял. Да можно в простом цикле это сделать. $r=[];foreach($m as $v)if($v)$r[$v]=0;
                На время почти не влияет если искать очень много: это делается один раз до поиска.
                  0
                  $m=array_combine($m,$m) делает массив уникальным без лишних вопросов.
                  array_flip меняет местами ключи и значения.
                  А это важно, что там в значениях, если у вас ключ уже искомая строка?! Вы туда можете хоть null подставить, памяти сэкономите.
                  Да можно в простом цикле это сделать. $r=[];foreach($m as $v)if($v)$r[$v]=0;
                  Код с ошибкой и отличается от работы array_combine или array_flip, вы потеряете все пустые строки.
                  $m = [''];
                  var_dump(array_flip($m));
                  var_dump(array_combine($m,$m));
                  $r=[];foreach($m as $v)if($v)$r[$v]=0;
                  var_dump($r);
                  
                  вернёт:
                  array(1) {
                    [""]=>
                    int(0)
                  }
                  array(1) {
                    [""]=>
                    string(0) ""
                  }
                  array(0) {
                  }
                  
                  А ваш пример отдаст пустой массив. Косяк)
                    –1
                    Вообще глупо искать пусто в массиве, у меня таких задач никогда не было и вряд ли это имеет практически смысл, но если сильно надо, то можно не искать а проверить строку на пусто и это быстрее в миллион раз.
                +1

                Что-то вы путаете тёплое с мягким.
                in_array() ищет значение в массиве, а array_key_exist() наличие ключа, а это две огромные разницы.

                  –1
                  Это тот же поиск строки в массиве строк, из тестов видно же, никаких фокусов и обмана. Возьмите массив миллиард строк и 10к строк для поиска. Надо узнать какие строки есть в этом массиве, а каких нет.
                  in_array() — это обычная ф-я, она для этого сделана. Но можно этот же массив превратить в массив индексов-строк для словаря(ассоц.массива) и тогда проверка есть ли такой ключ будет аналогом поиска в массиве, но здесь идет поиск по другому алгоритму (а именно через таблицу хешей, но об этом мало кто знает) и одинаковые и пустые значения запрещены. Но для поиска они обычно не нужны. Если надо, то на пусто можно проверять отдельно — это быстро.
                  Еще in_array() может искать 0, null,'' как пусто и значением может быть пустая строка, в индексах — не может, но '0', 0 — можно.
                    +2
                    Нет, вы путаете теплое с мягким. Это две разные операции, которые вы патаетесь взаимозаменить.

                    И проблема все же останется. На маленьких массивах вы не заметите разницы (разве что вы правда делаете млн операций на массиве из 10 строк, но это маразм). А вот массивы в миллиард реальных строк вас сильно удивят выделением памяти.

                    Массив на млрд. уникальных строк будет отжирать память довольно существенно. Когда вы сделаете array_flip (ну или ваш аналог) — память по сути увеличится в два раза, т.к. массива у вас уже два. Это короткий промежуток времени и там не совсем уж х2, но все же в реальном мире вы только проиграете.

                    С другой стороны, если для вас эта память не играет роли, то не совсем понятно какой поиск вы пытаетесь так оптимизировать. Будет выигрыш в копейки.

                    Говорю это из собственного опыта на массивах до 1 млн значений (ссылки). Проще сразу хранить их как ключи => bool, чтобы и isset() работал и не приходилось его флипать.
                      –1
                      Мне это реально помогло, вот и написал, может другим поможет тоже, памяти надо больше, сразу сказал. Надо экономить- искать частями, выгружать, загружать. Выигрыш есть, и не копейки, массив может прийти из вне, или из файла, пока что надо флипать его заранее или переделывать сам in_array() или писать на др. языке свой оптимальный поиск, выбирать размер хеш и алгоритм хеширования и считать по шагам что лучше, через хеш можно в нес-ко потоков искать, а бинарный поиск только в одном. тут 1байт-и делать хеш, там сортировка и сравнения. В разных случаях — наилучший свой.
                      Писали что в 7.2 улучшили этот поиск через обратный массив и хеш, но я сравнил — разница не заметна, сейчас через индекс быстрее и намного.
                        0
                        Просто вы говорите об этом как об одном и том же поиске. А по факту это просто разные вещи и вы одну структуру приводите в другую структуру. Как вариант — пойдет конечно, но нужно понимать что происходит.
                  +4

                  У меня получше тема для разговора: полезно ли программистам читать Кнута в 2020?

                    –1
                    очень полезно, я начинал с него, а еще лучше пару лет пооптимизировать машинный код после стандартных компиляторов- тогда сразу понятно как и что можно ускорить, я иногда в сотни раз после них ускорял.
                    +2
                    Хм, странно… это же принципиально разные вещи — поиск по хешу или по значению. Это все равно, что повесить индекс к столбцу в базе данных и удивляться, что стало быстрее… Или не делить на два, а битовый сдвиг вправо, или проверить на четность как a & 1, а еще можно использовать как битовые флаги.

                    Притянутая за уши ситуация, когда сделал для себя «открытие».
                      0
                      И ваше же решение для вашей же задачи не подходит:
                      Иногда нужно найти строку в массиве строк

                      Вы не находите строку, а просто говорите о наличииесть она там или нет. Чтобы найти строку есть array_search (для поиска первого вхождения) и array_keys для поиска всех вхождений — на выходе получаете ключ/массив ключей, которые содержат искомую строку.
                        –1
                        Вот когда тебе дадут реальное задание — есть миллион строк — слова/фразы/итд. биг дата, накопили за 10 лет. что то, и надо написать экспертную систему — которая в том числе и ищет в словарях — есть/нет и делает что-то, вот попробуй это сделать. Там не в 100 строках искать надо и времени надо очень много, тогда будешь писать это на си или можно найти способ попроще, ведь одну задачу можно решить разными путями, только затраты на разработку и время работы разное. Наличие строки это тоже поиск.
                          +1
                          Вот когда тебе дадут реальное задание — есть миллион строк — слова/фразы/итд. биг дата, накопили за 10 лет. что то, и надо написать экспертную систему — которая в том числе и ищет в словарях — есть/нет и делает что-то, вот попробуй это сделать.

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


                          А так-то да, это типовая задача, еще в MMDS разобранная.

                            +3
                            Если два вас бигдата — это то, что можно поднять в оперативу — то советую ознакомиться с машиной Тьюринга и его бесконечной лентой (читай — данные). Ну есть у меня в одном проекте база больше 500 Гб — ну так мускул с ней справляется без проблем — на сервере 32 ГБ оперативы. И это еще ни разу не бигдата, да, там есть пару-тройку тяжелых таблиц (гигов по 100 и миллиардами записей), которые нужно джойнить и фильтровать… Но это ладно.

                            Вы используете массивы как множество — это разные понятия, и пытаетесь притянуть за уши свой пример для «решения» задачи — хештаблицы и просто массив разные понятия. Если вы случайно сделали для себя открытие — поздравляю, мир об этом уже знает сто лет!
                          +2
                          Поиск строк на чистом ассемблере/си это сортировка массива строк (быстрая или пузырьковая), затем бинарный поиск.

                          Число шагов в бинарном поиске log(n) раз и зависит от размера массива, и намного меньше чем простой перебор.

                          Вы же, кстати, помните, что сортировка — это O(n log n)?


                          И с чего вы решили, что в in_array сделано так, а не простым перебором? Я, конечно, сварщик ненастоящий, но я никакой сортировки в исходниках не вижу.

                            –3
                            А где я писал какой алгоритм там? Вам опять показалось. Я написал какие алгоритмы поиска есть и как можно еще улучшить, то что есть сейчас, но здесь большинству даже просто проверить лень что способ просто рабочий без всяких объяснений, С кем тут о чем спорить? чтобы мне минусов наставили вместо спасибо? Мне это не надо. Да и вообще люди стараются, разбираются, изучают, делятся бесплатно полезной инфой и что? приходят хейтеры и минусуют, кому охота после этого что-то сюда писать и объяснять? На форумах чтобы поставить минус надо иметь большую репутацию и написать за что и это проверит модераторы и админ -защита от ботов, мультов и неадекватных.
                              0
                              А где я писал какой алгоритм там?

                              В цитате. Если это не имеет отношения к in_array, то зачем вы это вообще написали?

                            0
                            Наверное, момент, который может показаться непонятным — почему в PHP и массивы и хэш-таблицы называются одинаково array? Собственно, отсюда ноги и растут — потому что если мимо проходящий человек видит in_array/array_key_exists — ну да, конечно можно немного поразмыслить и понять разницу даже без документации, но все-таки когда и там и там «array», то это не очень прозрачно. И вот так и появляются такие, как топикстартер, решающие сделать, кхм, разоблачающее расследование.
                              0

                              Может, всё-таки наоборот, прозрачно, раз там и там array, значит и там, и там одно и то же?

                                0

                                Ну не одно и то же ведь. То он нормальный массив, то хэш-таблица.

                                  0

                                  Он всегда хэш таблица. Нормальных массивов в PHP нет (про SPL замнём для ясности), просто ключом может быть не только строка, но и целое.

                                –1
                                array это массив, индекс число.
                                ассоциативный массив это по сути словарь ключ-значение, у него индекс это строка.
                                В питоне это тип dict там понятней. в php/js это одинаково и числа это тоже как строки- быстрее не ищет, значит тоже по хеш, а не по смещению.
                                0
                                Вы сравнивали in_array не с array_key_exists, а с isset. Это несколько разные вещи хотя бы потому, что isset не является функцией и дает другой результат. Попробуйте добавить NULL в изначальный массив и посмотрите, что вам вернет isset при попытке узнать, есть ли в массиве этот NULL.
                                Про необходимость включения array_combine (или array_flip) в тело цикла для корректного сравнения вам уже выше написали. И если делать честное сравнение с array_flip+isset/array_key_exists, то получим результат в разы хуже, чем если бы использовали in_array.
                                  0
                                  Это уже обсуждалось выше 3 раза, на пусто проверять надо отдельно, и будет также в 500 раз лучше, спорим сразу на 10к? так как я знаю что говорю.
                                    0
                                    вы в своем варианте поиска не оставили себе возможности как-либо сделать эту проверку. потому что NULL не может быть ключем хеш-таблицы. При наличии, например, одновременно пустой строки и NULL в одном массиве, вы одно из этих значений потеряете и уже не сможете найти.
                                  0
                                  Уже комментировали, но я попинаю труп ещё раз.

                                  Вам, уважаемый, следует ознакомиться с hash таблицами. Совершенно две разные операции которые не взаимозаменяемы без танцев с бубном.
                                  Поиск вообще дело сильно зависящее от данных и его нужно подгонять под каждый конкретный случай где много данных. Не редки случаи, когда вместо in_array и прочих встроенных вариантов поиска написанный на голом PHP алгоритм может быть быстрее. Такое бывает не часто конечно, т.к. не очень умно гонять такие массивы данных в скриптовом языке, но случается время от времени.
                                    –2
                                    там комментировали трупы, можно их попинать, чтобы сходили проверили тесты раз, и написали свои тесты и проверили на своих серверах в разных версиях пхп и питона два.
                                    Хеш таблицы это отображение одного множества строк в другое. Каждый байт хеша уменьшает область поиска в 256 раз, а бинарный поиск=метод половинного деления делает это за 8 шагов в одном потоке.
                                    К сожалению на скриптовом языке сейчас много алгоритмов в том числе и связанными с обработкой биг дата, так как писать на норм. языке накладно. Нужно это редко и не всем, а понять судя по коментам может один из ста. Можно это как тест на IQ/знание алгоритмов и PHP использовать, кто не понял — тот пока junior :)
                                    +2
                                    Более бестолковой статьи я на хабре не видел за последние пару лет. Как ЭТО попало сюда?
                                    Автор путает кислое с мягким, пытается открыть какую-то истину, которую и так все знают.

                                    ЧСВ зашкаливает «Про текущий алгоритм отвечу когда мне +100 поставят, за попытку поделится с адекватными думающими людьми рабочим способом-костылем, исправляющим косяки разрабов, а не ерундой никому не нужной.»

                                    Чувак, какие плюсы. Твою статью и комментарии минусуют. Может это не просто так?
                                      –3
                                      А я видел коменты еще бестолковей. Статья уже такая была, но давно, получила 19 плюсов, я о ней не знал, когда стал эту постить — поискал на всякий случай чтобы не повторяться. Может тогда тогда люди умней были? В последнее время ботов и мультов много, сами себе накручивают, других топят. И не только здесь, в ВК дизлайки запретили.
                                        +3
                                        В последнее время ботов и мультов много

                                        написал аккаунт, которому меньше 2 недель

                                      +2

                                      Оказывается, как долго можно комментировать суффиксное дерево.

                                        –2
                                        Вы проверили эти тесты и алгоритмы? Быстрее стало или так же/хуже? Пока что никто не написал, все пишут какие то свои фантазии. Наверно никогда строки в массивах не искали.

                                      Only users with full accounts can post comments. Log in, please.