Форум программистов, компьютерный форум, киберфорум
Алгоритмы
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.72/18: Рейтинг темы: голосов - 18, средняя оценка - 4.72
12 / 12 / 5
Регистрация: 16.03.2010
Сообщений: 37

Предподсчет и поиск за одну секунду

12.05.2015, 19:46. Показов 4106. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте!
Поставлена такая задача: имеется массив из 100,000 пар "строка - число". Все строки уникальные, числа могут повторяться. Даётся 1 секунда на создание вспомогательных структур и предподсчет будущих результатов. После этого следует 100,000 запросов, в каждом из которых выполняется поиск 10 таких пар, что: строка начинается с указного префикса, а число как можно больше.
Выполнение всех этих запросов должно уложиться ещё в 1 секунду!
И ещё одно неприятное ограничение: используемая память ограничена 64 мб.

Подскажите, какие структуры можно использовать для решения?
Префиксное дерево (первое, что пришло в голову) уже безо всяких предподсчетов не укладывается в 64 мб. AVL-дерево по памяти проходит, но на выполнение одного запроса уходит (в среднем) 5 мс - слишком медленно.
Подскажите ещё варианты?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
12.05.2015, 19:46
Ответы с готовыми решениями:

Задержка в одну секунду
Как сделать в Си задержку в одну секунду?

Максимум 3 запроса за одну секунду.
Доброго времени суток. Есть JS который каждую секунду посылает POST в ajax.php - который в свою очередь обрабатывает. Максимально во время...

Вывод времени с обновлением в одну секунду
Прошу вашей помощи! Приветствую всех! Хотелось бы сделать так, чтобы оставалась шапка сообщений сверху и обновление посекундно тайма,...

13
Модератор
Эксперт функциональных языков программирования
3132 / 2279 / 469
Регистрация: 26.03.2015
Сообщений: 8,870
12.05.2015, 22:15
Какого размера числа?
Какой длины строки?

Добавлено через 1 час 3 минуты
Какие символы могут встречаться в строках?
1
 Аватар для krapotkin
6847 / 4674 / 1463
Регистрация: 14.04.2014
Сообщений: 20,656
Записей в блоге: 21
12.05.2015, 22:38
ну, без дерева точно никуда тут
по сути, имитируем поиск в БД с индексами

если строка 25 + число 4 то всего 2 мб набирается данных
что бы в 64 мб не уложиться с индексами ?
1
12 / 12 / 5
Регистрация: 16.03.2010
Сообщений: 37
13.05.2015, 15:08  [ТС]
Числа - long, по 8 байт каждое. Строки - не более 32 символов в unicode, только буквы и цифры. Итого 72 байта на одну пару, ~7 мб на все данные.

Опыты показали, что при таких условиях количество узлов в префиксном дереве приближается к 3 миллионам, то есть построить его целиком не выйдет - не хватит памяти.

Сейчас рассматриваю такой вариант: префиксное дерево для первых 8 символов (займет около 50 мб), дальше обычное дерево или даже просто список. Но быстро работать это будет только из расчета, что лишь несколько строк начинаются с 8 одинаковых символов.
Да и, честно говоря, пока слабо представляю, как это всё написать.

Ещё не указал одну деталь: реализовываться будет на Java.
0
221 / 166 / 47
Регистрация: 17.07.2012
Сообщений: 587
13.05.2015, 15:52
можно закинуть хеши всех префиксов в std:map<long long, int> - МАП из хеша префикса в макс число. ну и потом когда пришел запрос мы просто считаем хеш строки-запроса и берем значение из МАПЫ.
0
 Аватар для krapotkin
6847 / 4674 / 1463
Регистрация: 14.04.2014
Сообщений: 20,656
Записей в блоге: 21
13.05.2015, 16:10
префиксы для поиска фиксированной длины?
0
221 / 166 / 47
Регистрация: 17.07.2012
Сообщений: 587
13.05.2015, 16:25
krapotkin, не понял вопроса. вот есть строка S и соответствующее ей значение VAL. мы посчитаем хеши всех префкисов строки и все эти хеши закинем в МАП так: MAP[hash[i]] = max(MAP[hash[i], VAL); теперь когда пришел запрос строка мы считаем ее хеш. пусть он равен needHASH и тогда ответ на запрос равен MAP[needHASH].

Добавлено через 2 минуты
Dozer74, кстати откуда задача. чет она больно олимпиадная да еще и ограничения откуда то взялись. может соревнование какое идет?
0
 Аватар для krapotkin
6847 / 4674 / 1463
Регистрация: 14.04.2014
Сообщений: 20,656
Записей в блоге: 21
13.05.2015, 16:27
в задании сказано
10 таких пар, что: строка начинается с указного префикса, а число как можно больше
если префиксы фиксированной длины, то вполне можно эффективный индекс построить
я просто не знаю, как хэши реализованы в яве
0
Модератор
Эксперт функциональных языков программирования
3132 / 2279 / 469
Регистрация: 26.03.2015
Сообщений: 8,870
13.05.2015, 22:53
В качестве ключей я создаю случайным образом 100 тыс. строк по таким параметрам:
C#
1
2
3
    const string chars = "abcdefghijklmnoprstquvwxyz1234567890";
    const int minchars = 4;
    const int maxchars = 32;
Я строю дерево. Узлов в нём меньше, чем 150 тыс.
Время на построение меньше 0.5сек.

Случайным образом строю 100 тыс запросов.
Выполняю все запросы.
Общее время меньше 0.05сек.

Добавлено через 4 минуты
Описание дерева:

Добавлено через 9 минут
Мне лень было самому двоичный поиск в отсортированном массиве писать , поэтому я использую SortedList<char, int>:
SortedList<TKey, TValue> is implemented as an array of key/value pairs, sorted by the key.
The SortedList<TKey, TValue> generic class is an array of key/value pairs with O(log n) retrieval.

Так выглядит узел дерева:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
public static int NodeCount = 0;
public class Node
{
    public int Number;
    public SortedList<char,Node> Children;
    
    public Node(int number)
    {
        Number = number;
        Children = null;
        NodeCount++;
    }
}
Нужно его заменить на структуру Node с полями: char, long, *Node, где *Node - ссылка на отсортированный массив.

Добавлено через 8 минут
Алгоритм построения дерева:
1. Сортируем данные по ключу (строке).
2. Для каждой строки данных:
Пока префикс ключа совпадает с префиксом предыдущего: идём по дереву, обновляя, если нужно число.
Добавляем узел с текущим символом ключа.
Пока префикс не станет отличаться от префикса следующего: добавляем узел с текущим символом.

Добавлено через 5 часов 42 минуты
Запускал я только дебаг версию (без оптимизации). С оптимизацией немного быстрее получается.

Я переписал с использования SortedList на обычный List (обычный массив с логикой для автоматического увеличения размера). Так как массивы у меня маленькие, то линейный поиск не сильно медленней получается.

А вот с памятью сложнее. Для оптимизации по памяти нужно свой менеджер памяти писать, а мне лень (массивы по ходу работы нужно переаллоциловать - значит за "дырками" следить и т.д.). Потом каждый экземпляр класса - это дополнительный расход памяти. Класс нужно на структуру заменять, а в C# нельзя структуру из функции по ссылке вернуть... значит код переписывать. Сейчас по памяти я укладываюсь с большим запасом... но это на случайных данных. Неизвестно, что будет, если специально конструировать данные, которые потребуют максимума памяти.

Сейчас время примерно такое:
Generate tree: max = 100000, time = 00.0771723
Memory used: 43,56 Mb
Find: max = 100000, time = 00.0589016

Добавлено через 3 минуты
Расход памяти - это то, что процесс под себя забирает. Я из под LinqPad запускал... там даже при n = 10 сразу 32 Mb...

Добавлено через 4 минуты
С линейным поиском в два раза медленнее ищется, но запас есть.
0
1963 / 819 / 114
Регистрация: 01.10.2012
Сообщений: 4,766
Записей в блоге: 2
14.05.2015, 08:26
Не понял что здесь дает дерево если оно строится по одному ключу (строка). Просто отсортированный массив и линейный поиск в диапазоне lower_bound/upper_bound даст ту же скорость. Если все строки начинаются c заданного префикса - увы, дело сведется к линейному перебору.

Заменим строку на "тоже число", получаем задачу: найти точку (x, y) с максимальным y и x в заданном диапазоне значений. Здесь хорошо подходит напр BSP, AABB - т.е. задача сводится к хорошо известной. Просто это замаскировано "строкой" (и ловушка сработала )
0
Модератор
Эксперт функциональных языков программирования
3132 / 2279 / 469
Регистрация: 26.03.2015
Сообщений: 8,870
14.05.2015, 11:28
Цитата Сообщение от Igor3D Посмотреть сообщение
Не понял что здесь дает дерево если оно строится по одному ключу (строка).
Я, наверное, непонятно объяснил. Проще показать на примере.

Вот исходные данные и дерево, которое я строю:
(на синие числа не обращайте внимания - их линкпад добавляет при выводе.
Миниатюры
Предподсчет и поиск за одну секунду   Предподсчет и поиск за одну секунду  
0
1963 / 819 / 114
Регистрация: 01.10.2012
Сообщений: 4,766
Записей в блоге: 2
14.05.2015, 13:56
Цитата Сообщение от Shamil1 Посмотреть сообщение
Я, наверное, непонятно объяснил. Проще показать на примере.
Все равно не понял в чем смысл Ну вот допустим все строки начинаются с "а" который и есть префикс. Будут ли перебраны все эл-ты Вашего дерева или все-таки оно что-то отсечет?
0
Модератор
Эксперт функциональных языков программирования
3132 / 2279 / 469
Регистрация: 26.03.2015
Сообщений: 8,870
14.05.2015, 14:07
Цитата Сообщение от Igor3D Посмотреть сообщение
у вот допустим все строки начинаются с "а" который и есть префикс.
В списке, состоящем из единственного элемента, найдёт узел Char == 'a'. И тут же вернёт ответ - значение Number данного узла.

Добавлено через 4 минуты
На картинке видны ответы (максимальные числа) для всех префиксов:
Кликните здесь для просмотра всего текста
a 9930
ab 740
ac 9930
aca 7820
acac 7820
acaca 545
acacb 7820
acb 1596
acc 9930
accb 9930
и так далее
1
1963 / 819 / 114
Регистрация: 01.10.2012
Сообщений: 4,766
Записей в блоге: 2
14.05.2015, 14:33
Цитата Сообщение от Shamil1 Посмотреть сообщение
В списке, состоящем из единственного элемента, найдёт узел Char == 'a'. И тут же вернёт ответ - значение Number данного узла.
Теперь понял, спасибо. Да, быстрее поиск пожалуй не сделать
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
14.05.2015, 14:33
Помогаю со студенческими работами здесь

Как задержать цикл на одну секунду
Помогите пожалуйста, не как не могу приостановить цикл на секунду, мне надо сделать так чтобы каждую секунду цикл выводил текст, пробовал...

Как засечь ровно одну секунду?
Хочу написать консольку, которая будет считать, сколько действий в секунду выполнит мой комп. Проблема: не знаю, как засечь эту...

Добавить одну секунду к заданному времени
Доброго времени суток. У меня есть проблема, помогите мне ее решить. Дана задача: Даны 3 целых числа, представляют собой запись...

Вывести время на одну секунду большее
На вход подаются три числа, показание электронных часов, в формате часы, минуты, секунды. Например, 20 17 59 -- двадцать часов, семнадцать...

Определить время, на одну секунду больше заданного.
Задано время в часах, минутах и секундах (h, m, s) (0 ≤ h ≤ 23, 0 ≤ m, s ≤ 59). Определить время, на одну секунду больше заданного!


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru