LINUX.ORG.RU

Группы по алготритмам и подсказки от лора

 big fuckin data, ,


2

3

Где есть живые (англоязычные с хорошим траффиком приветствуются) группы алгоритмических тусовок, конкретно вокруг структур данных. Нужны мозги.

Проблема следующая есть данные задаваемые в виде таких векторов

([a,b,c], [1,3].....[T,F]) -> X1
...
([a,b,c], *, *, 1, ..[T]) -> X2

То есть векторами длиной N где каждый элемент является списком допустимых значений. Таких X - скажем меньше сотни тысяч. Нужно делать по этому множеству позиционные запросы вида

(a, 1 | 2, * ... F)

Внимание задача - нужно делать их быстро: <30ms, 1000+qps. Всякие spatial data structures(k-d, r и прочие деревья) я разрыл - оно то работает, но только требует океаны памяти. Например при N=20 при преобразовании в точки, если X определен 2мя значениями в каждой позиции то это 2^20 точек на один X. Берем таких 100k x 1M = 100G точек.

То есть как-то работаю пока * в данных много - еще как-то помещаюсь хоть куда-то с небольшим кусочком - но до нужных цифр пока как до неба.

Ключевые слова или ссылки на группы где тусуют люди которые могут знать ключевые слова приветствуются.

★★★★★

Последнее исправление: r (всего исправлений: 2)

Нужны мозги

стаковерфлоу?

есть данные задаваемые в виде таких векторов
векторами длиной N где каждый элемент является списком допустимых значений

А расскажите немного подробнее. N - это сколько? Что такое * - любое? Допустимые значения - это набор байт? Как задается позиционный запрос? Набор байт из запроса должен точно совпадать с набором из вектора?

anonymous
()

Просто хранить элементы вектора в set (AVL-tree), если большой элемент - perfect hashing строить заранее по этому списку?

anonymous
()

1) Это работа с множествами?
2) Если да, то максимальное количество элементов одном множестве?

vada ★★★★★
()

вероятно, глупость скажу - а вам не поможет чуть модифицированное дерево поиска? на каждый из N элементов по дереву, а для списка значений допускается повторное включение элемента для каждого элемента списка.

anonymous
()

<30ms
N=20 при преобразовании в точки, если X определен 2мя значениями

И это бигдата? (20*2*4(sizeof(int))*100*1000) - это 15метров. 4метра на чарах. Знаешь скорость линейного поиска? Упирается чисто в память - на современном железе это в районе 12-15G на канал минимум. Сам посчитаешь? Скорость л3 в районе 20-30G на ведро. Сам посчитаешь?

30мс - это ничто в сегоднящних реалиях для таких цифр.

Опиши по конкретней задачу - я тебе накатаю примеров.

anonymous
()

Возможно, я не очень понял задачу (может, пример привести - было бы понятнее), но почему бы не рассматривать ее как обычный поиск с boolean queries?

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

Если данные более-менее статичные, то задача довольно простая (100 тысяч документов - это ерундовое кол-во). Если нет - чуть посложнее, надо сделать эффективные обновления индекса.

Если N фиксированное и не очень больше, то все можно сделать еще проще - на каждую позицию свой индекс.

moroz ★
()
Ответ на: комментарий от anonymous

N <= 50
* любое
допустимые значения могут быть инты, даблы, строки

Как задается позиционный запрос?

(a, 1 | 2, * ... F)

Набор байт из запроса должен точно совпадать с набором из вектора?

По позициям. В вышеприведенном подходят вектора где в первой позиции в списке есть элемент «a», во второй позиции 1 или 2, в третьей любой.... в последней False.

r ★★★★★
() автор топика
Ответ на: комментарий от anonymous

вероятно, глупость скажу - а вам не поможет чуть модифицированное дерево поиска?

Как я уже сказал деревьев разных было рассмотрено много, и текущее решение и работает с мутировавшим К-d деревом. Но как показано - все подобные решения работают с т.н. пространством точек - то есть на гиперплоскости задается точка с координатами вектора. У меня в векторах списки допустимых кординат. То есть для сведения к гиперпространству надо их разложить в простые вектора - это декартово произвидение всех списков вектора. Как видно при N=20 и не более 2х значений в позиции вектора - количество перестановок 2^20=1M. При 1000 таких элементах и 100 байтах на значение объем потребляемой памяти 100G. А мне надо десятки тысяч и списки там подлинее. То есть не все так просто.

r ★★★★★
() автор топика
Ответ на: комментарий от anonymous

это 15метров.

Ага щаз. Количество перестановок при N=20 это не 20*2, а 2^20.

r ★★★★★
() автор топика
Ответ на: комментарий от moroz

что разные слова могут занимать одну и ту же позицию

Это существенное отличие с точки зрения объема операций. Если там одно слово =- то это одна операция сравнения (индексированная или нет не важно). А если там списки - все возводится в соответствующие степени. Вектор:

([1,2], [a,b]) -> X1

В линейный индексируемый вид разворачивается в 4 записи.
(1,a) -> X1
(1,b) -> X1
(2,a) -> X1
(2,b) -> X1

Добавь третью координату с двумя значениями - и записей уже 8, Добавь в первую позицию еще одно значение и записей уже 16. А у меня в такой позиции может быть 1-50 элементов, и таких позиций до 50, Если возьмем что средняя длина списка в координате 5 это 5^50 перестановок для одного X. А таких X до 100к.

r ★★★★★
() автор топика
Ответ на: комментарий от r

А сетка if-ов, с подачей рандомного снаряда/шаблона на вход и с рандомными условиям выбора варианта/ветвления, разве не быстрее будут ?

У тебя никаких требований к закономерности генерируемых данных нет?

anonymous
()
Ответ на: комментарий от anonymous

А сетка if-ов,

Ине не генерировать - но насчет хардкода это надо подумать.

r ★★★★★
() автор топика
Ответ на: комментарий от r

А зачем все варианты хранить?

Пример:

X1 = ([1,2], [a,b])
X2 = ([1,3], c, F)

Индекс:
1 -> (1, X1), (1, X2)
2 -> (1, X1)
3 -> (1, X2)
a -> (2, X1)
b -> (2, X1)
c -> (2, X2)
F -> (3, X2)

Запрос:
(1, a | c, *)

Исполнение:
1) поднять пост-лист для слова "1", выбрать все элементы с позицией 1
2) поднять пост-лист для слова "а", выбрать все элементы с позицией 2
3) поднять пост-лист для слова "с", выбрать все элементы с позицией 2
4) объединить результаты пунктов 2 и 3
5) пересечь результаты пунктов 1 и 4

С точки зрения объема индекса ситуация «x элементов, в каждом элементе y вариантов» не отличается от ситуации «x * y элементов». В задачах текстового поиска без проблем индексируются коллекции в миллионы документов размером ~тысячи слов на документ.

Единственная проблема - если в векторах могут быть элементы «*». Но ее можно обойти, например, завести специальное слово '*' и обрабатывать, как будто оно есть в запросе на всех позициях.

moroz ★
()
Ответ на: комментарий от moroz

Это фактически отдельные индексы по разным измерениям. Первые игры были на эрланге - я так и попробовал - там это эпически дорогая операция. Но пересечение - это O(N)+ операция. Разбиение по true/false на 2 - это перебор 100k/2 элементов минимум при пересечении с этими результатами. Плюс по памяти оно будет кушать на каждый запрос мегабайты - представь 50k элементов в виде массива указателей по 4байта - 200k скушает только лукап по boolean пространству.

В задачах текстового поиска без проблем индексируются коллекции в миллионы документов размером ~тысячи слов на документ.

Одномерно. В этом проблема Nслов^(k=1)=N. А у меня Nслов^(k<=50). Даже при маленьких N это охрененные числа.

r ★★★★★
() автор топика

Попробуй слепить списки в строку и создать полнотекстовой индекс для каждого поля. Можно попробовать round-robin scheme для ускорения поиска по многим индексам.

Для проверки идеи, можно использовать picolisp, поскольку там это уже сделано.

anonymous
()
Ответ на: комментарий от r

Все-таки я не понимаю, почему N ^ k, а не N * k. В моем примере - где я не прав? Можешь привести пример, где будет видна разница?

moroz ★
()

Плюсую анонима, посылающего на SO.

Eddy_Em ☆☆☆☆☆
()

1. берём учебник по алгоритмам полнотекстового поиска

2. вдумчиво читаем

3. ....

4. PROFIT!!!11

anonymous
()
Ответ на: комментарий от r

N <= 50

Вроде бы не очень много? Можно попробовать такой наивный алгоритм:

- Берем исходные вектора. Для каждого столбца выбираем уникальные элементы (и сортируем). Для каждого уникального элемента храним номера строк (векторов) в которых они находятся. Если элементов немного (True/False например), то можно для каждого элемента построить битовую карту

- Для каждого запроса берем пустую битовую карту. Элемент из запроса ищем в соотв. столбце (бинарным поиском). Обновляем битовую карту выборки. И так N раз

anonymous
()
Ответ на: комментарий от moroz

Все-таки я не понимаю, почему N ^ k, а не N * k

0|1, 0|1, 0|1 - сколько существует перестановок? Это позиционный двоичный код - 2^3.

В моем примере - где я не прав?

В твоем примере в конце операция сложностью k(пространств)*O(N)+(пересечение множеств, сложность зависит от алгоритма либо O(N^2) либо 2*O(NlogN) + O(N) в случае сортировкой). Не говоря уж о памяти.

То есть алгоритмически работать будет. А вот скорость....

r ★★★★★
() автор топика

если есть ограничение на память, то я бы стал думать в сторону правила преобразовании ([a,b,c], [1,3].....[T,F]) -> (N1, N2, ..., Nn), где N это обычные числа. В приведённом примере это может быть обычное OR всех значений в перечислении, * - это FFFFF. Приводишь запрос в такие же числа по тому же правилу. Тогда полным перебором по всем цифрам с AND получишь ограниченный набор данных, который можно полностью перебрать и получить результат. Проверок будет очень много, но они элементарные и легко раскладываются по ядрам, оверхед по памяти фактически отсутствуют. Можно сократить перебор приведя его к тройной схеме т.е. ([a,b,c], [1,3].....[T,F]) -> (N1, N2, ..., Nn) -> N сначала с проверкой по N формировать набор данных для проверки по вектору чисел Nn, который формирует окончательный набор для проверки. ну это навскидку, предполагая что запрос формирует достаточно ограниченный набор данных.

vtVitus ★★★★★
()
Последнее исправление: vtVitus (всего исправлений: 1)
Ответ на: комментарий от r

Откуда перестановки-то? Для поиска не нужно все эти варианты генерировать.

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

Индекс, конечно, в памяти целиком никто не хранит, но это не проблема.

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

moroz ★
()

А алфавит конечный? В смысле допустимо ли заменить

([a,b,c], [1,3].....[T,F]) -> X1

на

([a,b,c], [d,e], ... [y,z])

Если так, то почему обычные регулярные выражения не катят? Скажем если элементы векторов это слова состоящие из нескольких букв, то поиск это просто матчинг регекспа.

ebantrop ★
()

нужно делать их быстро: <30ms

Таких X - скажем меньше сотни тысяч

Я может чё-то не понимаю и скажу глупость, но проц 4ГГц за 30мс выполнит 120млн. тактов т.е. по ~1000 тактов на один вектор. Какгбэ даже линейный поиск по образцу должен справляться с задачей.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

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

Феном 3GHz, на одном ядре, вызов функции в которой одна битовая опперация ~1G операций на жабе. 80тыс строк реальных данных. N=50 => 4M операций если превратить все в биты. Это 250qps. Мало. У меня сейчас на модификации k-d дерева >1200.

r ★★★★★
() автор топика
Ответ на: комментарий от r

Феном 3GHz

Судя по мануалу на твоё говно(это же к10?) с ведра ты можешь снять 1Терабита на битопах.

вызов функции в которой одна битовая опперация ~1G операций на жабе

bigdata
latency
java

Ну ты понял.

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

80тыс строк реальных данных. N=50 => 4M операций если превратить все в биты.

Операций над чем? 1Терабит, 4М интов - это 128мегабит. Какбэ оцени разницу.

4М интов - это <16мегабайт в секунду. 16мегабайт - нутыпонял.

Если же у тебя 80к «векторов» по 50битов - это 4мегабита - это полмертра. Полметра в секунду - нутыпонял.

Это 250qps.

Что такое «qps»?

У меня сейчас на модификации k-d дерева >1200

Пацан снял отсилы 20метров/с на феноме. Куллстори.

anonymous
()
Ответ на: комментарий от no-such-file

Так бы сразу и сказал.

Какая разница? Ты думаешь bitwise or будет на сях быстрее чем на жабе настолько радикально что это будет иметь значение?

Ну а на 4 ядрах будет 1000qps, так?

Это порог - все данные надо сводить к битовым маскам и получим мы предел для четірех ядерного приложения. Как я сказал на том же ядре с помощью k-d дерева я делаю 1200qps. А там у меня еще мешок мыслей что можно оптимизиорвать.

r ★★★★★
() автор топика
Ответ на: комментарий от anonymous

с ведра ты можешь снять 1Терабита на битопах.

Это если ничего не делать кроме этих битопов. Мне не эмбеддед в 5килобайт написать надо а кластеризуемый сервер. Проблема не теоретическая - потому решения вида «заточить все на асме» не работают.

Ну ты понял.

Да а понял что ты теоретик. Проходи.

Операций над чем?

Битовых операций. Читать научись.

Что такое «qps»?

Запросов в секунду. Это ты уже сначала читать научись - а потом уже переходи к посылам.

Куллстори.

Мнение чувака который даже не осилил понять задачу - очень важно для нас.

r ★★★★★
() автор топика
Ответ на: комментарий от r

Это если ничего не делать кроме этих битопов.

А что тебе надо делать, кроме них? Ты хоть приведи пример своих реальных данных - тебе поцаны покажут как надо, а так это лишь жалкий кукаретинг.

Яж тебе говорил про память - это с твоей говнопамятью отсилы 12гигов на канал - это меньшее, чем 100гигабит. У тебя есть овер 10операций над каждым битом - тебе мало? На avx(2) - это уже 20операций на каждый бит.

Мне не эмбеддед в 5килобайт написать надо а кластеризуемый сервер.

16метров/с - да, куллстори. Я тебе сказал - хочешь познать некстлевел - выкатывай «реальные данные». Покачто ты прикрываешься жалким кукаретингом.

Сколько же нулю надо нод, чтобы снять 30гигов - датычё 2к. Неслабо. Кластерезуй дальше.

Да а понял что ты теоретик. Проходи.

Ахахаха, кукарекнул жабист, который снял 1G. В отличии от тебя я не теоретик - я понимаю что и как можно снять, и реально ли это.

Запросов в секунду. Это ты уже сначала читать научись - а потом уже переходи к посылам.

Каким образом у тебя может быть 1200запросов, если у тебя время поиска 30мс это хорошо? Чего запросов? К чему запросов? В отличии от тебя я не кукарекаю хрен знает о чем.

Мне не интересна что значит твоя абривиатура. Ты мне скажи с какого бадуна ты её выкатил и как считал.

Мнение чувака который даже не осилил понять задачу - очень важно для нас.

Ты не описал задачу - ты написал какое-то говно, невнятное и идиотское. Для тебя, нулёвого балабола - это возможно что-то из себя представляет, для пацана же, чьи познания в теме чуть больше нуля - твоё объяснение настолько же не точно, насколько твоё представление о реальном мире.

Выкатывай свои «реальные данные», критерии поиска, внятные примеры. А лучше выкладывай объяснение и того для чего тебе это нужно, ибо с таким уровнем с шансом 98% твоё представление о решении твоей задачи - тотальное говно.

anonymous
()
Ответ на: комментарий от r

Какая разница? Ты думаешь bitwise or будет на сях быстрее чем на жабе настолько радикально что это будет иметь значение?

Ты реально не понимаешь, что в х86 «alu» векторное и конвейерное? Я даже не знаю как идиоту это объяснить - почитай хоть что такое latency и throughput у инструкций. Зависимость по данным.

Суть не в том, что жаба говно - суть в том, что ты говно + жаба говно, поэтому у тебя 3такта на битоп, хотя у него latency 1такт. Я уж не знаю какой жопой надо забенчить, чтобы получить 1G, но ты явно уникум.

Это порог - все данные надо сводить к битовым маскам и получим мы предел для четірех ядерного приложения.

Ну не смеши меня, 1G на ведро. На умножении ты вообще наверное 0.8gflops получаешь на 4ведра. Куллстори.

Явно уникум.

anonymous
()
Ответ на: комментарий от anonymous

В отличии от тебя я не теоретик - я понимаю что и как можно снять, и реально ли это.

Ты мне тут рассказываешь про брутфорс а если надо больше то надо все переписать поближе к железу и и добавить ядер. С таким подходом - проходи.

Чего запросов? К чему запросов?

То что куча народу все прекрасно поняла а ты не догнал - о чем тебе говорит?

В отличии от тебя я не кукарекаю хрен знает о чем.

Ты даже на понял о чем ты кукарекаешь.

Ты не описал задачу - ты написал какое-то говно, невнятное и идиотское.

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

r ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Я уж не знаю какой жопой надо забенчить, чтобы получить 1G, но ты явно уникум.

вызов функции в которой одна битовая опперация
вызов функции в которой одна битовая опперация
вызов функции в которой одна битовая опперация

Ты дебил сначала научись читать.

Проходи уже, не интересен.

r ★★★★★
() автор топика
Ответ на: комментарий от r

Ты дебил сначала научись читать.

Как же смешат эти бомжи, которые даже не понимаю почему они в говне.

Понимаешь идиот - твоя функция будет выдавать абсалютно разные результаты в зависимости от её аргументов и того, куда ты её впихнёшь.

На твоём феноме, при 32битных интах:
//это 2такта.
a = xor(a, 123); b = xor(b, 123); c = xor(c, 123) 
a = xor(a, 123); b = xor(b, 123); c = xor(c, 123) 
//это тоже(2.33)
a = xor(a, 123); a = xor(a, 123); a = xor(a, 123);
//и это(2)
a0 = xor(a0, 123), a1 = xor(a1, 123), a2 = xor(a2, 123), a3 = xor(a3, 123);
b0 = xor(b0, 123), b1 = xor(b1, 123), b2 = xor(b2, 123), b3 = xor(b3, 123);
c0 = xor(c0, 123), c1 = xor(c1, 123), c2 = xor(c2, 123), c3 = xor(c3, 123);

Вечер маленьких открытий для нулёвого ущербана. Ты хоть что-то по примитивной матчасти почитай. Ещё раз повторю, эта область состоит из нюансов на 100%, и где нулёвый ущербан типа тебя ничего не видит - норма пацан понимает и видит нюансы из которых перфоманс и состоит.

Этим и отличается нулёвая ссанина, которая ничего не может, кроме как кукарекать и нести херню от пацана, который видит и понимаешь как надо, что и почему.

Но обоссаному нулёвому жабисту это не надо, ты ещё не дорос до чего-то чуть быстрее калькулятора. Иди бигдать, 16метров/с.

anonymous
()

то это 2^20 точек на один X

А зачем тебе из X получать точки?

А лучше скажи некоторые характеристики твоих данных и запросов:

  • Пусть в i-м списке вектора могут находится только элементы множества мощьности x(i). Какова сумма x(i) для всех i?
  • Пусть в запросе на i-м месте стоит дизъюнкция из y(i) элементов. Чем ограничена сумма всех y(i)?

P.S. А ты знаешь, что объединение или пересечение k списков по N элементов каждый можно сделать за O(N*k*log k)?

anonymous
()
Ответ на: комментарий от anonymous

А зачем тебе из X получать точки?

1. Это оценка количества перестановок для превращения в плоскую таблицу - объяснение почему «загнать в постгрес» не поможет.

2. Для создания индексирующей структуры вида K-D/R/X и прочих деревьев - превращение в spatial space.

Какова сумма x(i) для всех i?

Скажем в среднем 20 * <=50 = 1000. В реальности там могут быть весьма открытые списки - но вводит их все же человек - поэтому там могут быть множества из 10 элементов в основном - но есть несколько полей где встречается пара тысяч. Таких X мало но они есть - хотя я пытаюсь это пресечь административно - потому что они неверно пользуются системой. Это мощность введенных множеств. Часть из них в принципе бесконечные.

Чем ограничена сумма всех y(i)?

в среднем где-то 50 + 25. Дизъюнкции на практике могу появляться только в некоторых позициях и они небольшие.

А ты знаешь, что объединение или пересечение k списков по N элементов каждый можно сделать за O(N*k*log k)?

Знаю. При true | false лучший случай это бинарное рассечение пространства - N слишком большой.

r ★★★★★
() автор топика
Ответ на: комментарий от r

Часть из них в принципе бесконечные

Это как? Почему раньше не сказал?

anonymous
()
Ответ на: комментарий от r

N слишком большой.

Здесь N — количество векторов списков. Ты раньше говорил, что оно у тебя не превосходит 100 000. Это, разве, слишком много.

anonymous
()
Ответ на: комментарий от r

1. Это оценка количества перестановок для превращения в плоскую таблицу - объяснение почему «загнать в постгрес» не поможет.

2. Для создания индексирующей структуры вида K-D/R/X и прочих деревьев - превращение в spatial space.

А если использовать битовые строки?

Всё ещё не понимаю почему ты зациклился на распаковке своих векторов.

anonymous
()
Ответ на: комментарий от anonymous

Это, разве, слишком много.

А разве мало? Пересечение k=50 N/2.

r ★★★★★
() автор топика
Ответ на: комментарий от anonymous

А если использовать битовые строки?

Как я уже говорил - брутфорс 1G операций на ядро, 80к реальных строк x 50 измерений = 4M -> 250 запросов в секунду.

Всё ещё не понимаю почему ты зациклился на распаковке своих векторов.

Я не зациклился - просто первое решение это - вариант k-d дерева а следовательно надо превратить в spatial space.

r ★★★★★
() автор топика
Ответ на: комментарий от r

spatial space

Что это такое? Гугл такого не находит (по крайней мере не в начале выдачи), а дословный перевод даёт тавтологию: пространственное пространство.

anonymous
()
Ответ на: комментарий от r

Я про битовые строки в postgres. Я не знаю используется там брутфорс или всё это несколько оптимизируется, поэтому только предположил.

anonymous
()
Ответ на: комментарий от r

Я не зациклился - просто первое решение это - вариант k-d дерева а следовательно надо превратить в spatial space.

А почему же тогда ты все предложенные тебе идеи рассматриваешь с точки зрения векторов значений, а не векторов списков значений? Первое пришедшее тебе в голову и нужное тебе решения — вовсе не обязана совпадать или быть как-либо связаны между собой.

anonymous
()
Ответ на: комментарий от anonymous

Что это такое?

spatial data structures

r ★★★★★
() автор топика
Ответ на: комментарий от anonymous

А почему же тогда ты все предложенные тебе идеи рассматриваешь с точки зрения векторов значений, а не векторов списков значений?

:) я не рассматриваю:) Пока тут не предложили то что я уже и так знаю - я просто показываю даунсайды того или иного решения. С раздельной индексацией по каждой координате раздельно - дорогая операция пересечения которая сказывается на производительности. Брутфорс битовых масок - недостаточно производителен. Я сейчас провожу разные испытания разных решений. Есть еще битмап индексы, стратегии кластеризации R и X деревьев, состгресовские реализации для GiST и т.д. Я всем этим займусь. Просто я надеялся на ссылки на что-то принципиально другое, что я не нашел по ссылкам, какие-то другие предложения по сведению данных к другому представлению и следовательно другим алгоритмам.

r ★★★★★
() автор топика
Ответ на: комментарий от r

Брутфорс битовых масок

Или мы с тобой по разному понимаем брутфорс, или этого тебе никто не предлагал.

anonymous
()
Ответ на: комментарий от r

Странный ты. Характеристики данных из тебя вытаскивать надо. Есть указания про 30 мс и 1000 з/с, но ничего не сказано о железе?

Ну да ладно. Я выскажу свою идею, а ты делай, что хочешь.

Есть «массив» списков. Индексами массива являются:

  • значение
  • позиция в векторе этого значения

Т.е. для каждого значения в списке векора будет столько элементов массива, в скольких позициях вектора он встречается. Списки этого массива в качестве элементов содержат номера векторов в порядке возрастания (номеров). При выполнении запроса отбираются соответствующие списки этого массива и одновременно итерируются следующим образом:

  • первоначально у каждого списка активен первый элемент,
  • затем перебираем все номера векторов начиная с наименьшего (очевидно, что значения всех активных элементов списков будет не менее текущего номера — это будет частью инварианта цикла);
  • для каждого номера вектора просматриваем все активные элементы списков: если номер равен активному элементу списка, то
    • вектор удовлетворяет соответствующей части условия запроса и
    • в списке активных становится следующий элемент;
    если не равен, то, очевидно, ветор не удовлетворяет соотвтствующей части условия запроса; если у списка нет активного элемента (всче просмотрены), то вектор условию не удовлетворяет
  • после просмотра всех активных элементов списков нам известно удовлетворяет ли вектор запросу

Как видно, имеется два вложенных цикла. Тело внутреннего выполняется не более 100 000 * 50 = 5 000 000 раз.

Так как о железе ты ничего не говорил, то я не знаю подойдёт тебе это решение или нет.

anonymous
()
Вы не можете добавлять комментарии в эту тему: топик перемещен в архив.