помогите придумать структуру данных
Имхо надо отсортировать множество шаблонов и построить бор
а как соотносятся числа 2^N и n?
если первое сильно меньше, то можно очевидно ускорить
тупое сравнение имеет сложность N*n, так что твой вариант действительно медленныйну как, медленный в зависимости от n
n=100
2^N * log n = 512*7 = 3584
N*n = 9*100 = 900
n=1000
2^N * log n = 512*10 = 5120
N*n = 9*1000 = 9000
сколько строк для обработки?
а как соотносятся числа 2^N и n?я не знаю даже примерно какое будет n
если первое сильно меньше, то можно очевидно ускорить
но наверна нада рассчитывать что оно будет большое
просто если оно маленькое, то любой алгортитм довольно быстро отработает и это неинтересно
давай положим n>5000
входные строки по нему прогоняются.
сколько строк для обработки?очень много
не даже больше: ОЧЕНЬ много
на основе заполненных клеток в шаблонах (которые без звездочек) строится сбалансированное дерево.поподробнее плз...
входные строки по нему прогоняются.
Я бы понял ещё N*log(n) и обойтись без сравнений, что, собственно, и хотел предложить.
ОЧЕНЬ многоу тебя streaming процесс (т.е. новые "запросы" поступают постоянно) или stand-alone (по нажатию на большую красную кнопку обработать сто тыщ миллионов строк)?
Имхо надо отсортировать множество шаблонов и построить боркстати
это первое что мы на доске на работе нарисовали...
чо, реально на этом остановится?
Я бы понял ещё N*log(n) и обойтись без сравнений, что, собственно, и хотел предложить.блин, ну N*log(n) наверна и правда правильнее
и то нет, зависит от структуры, ну типа это всё равно быстро должно быть
вон в том же боре попробуй оценить скорость узнавания есть этот элемент там или нет, зависит же от того как реализованы узлы бора, биты до 100 не пойдут, число 100 нифига не фиксировано
у тебя streaming процесс (т.е. новые "запросы" поступают постоянно) или stand-alone (по нажатию на большую красную кнопку обработать сто тыщ миллионов строк)?первое
там мне потом надо будет отобранные шаблоны отсортировать
и выяснить есть ли такой набор шаблонов уже, если нет то создать
ну это уже какая нить хешмапа, там нада каждому набору потом значение некое посчитать
можно было бы на старте сразу все варианты посчитать, но их же дофигища, памяти стоко не будет и долго
вот что еще наверна важно
в реальном потоке довольно часто будут подаваться те же самые строки
но вот их захешить не оплучится, дело в том что изначальные шаблоны в процессе работы проги тоже могут меняться, редко но могут
ну или токо если хеш поданных строк вычищать при смене изначальных шаблонов, вощем это потом видно на практике будет...
поподробнее плз...на чем можно выиграть сравнения?
на отсечке заведомо не работающих шаблонов
допустим у нас есть шаблоны
1, *...
5, *...
10, *...
134, *...
тогда сравнив первое число строки с третьим вариантов, и узнав что строка больше, то варианты 1 и 2 можно не рассматривать.
после того как полностью сравнили первую цифру переходим ко второй и т.д.
соответственно, задача сводится к стандартному поиску по дереву, за одним исключением, что есть еще "звездочные" ветки, которые чуть более хитрые (если одна из подветок дерева "звездочная", то она обходится в любом случае)
если вдруг максимального нет, то длинну строк и шаблонов надо измерять в битах, а не в позициях
Думаю, что для n=5k какой-нить grep -f будет работат достаточно быстро, если в шаблонах вместо * написать [0-9]* и окружить всё ^$, чтобы не выдумывать собственный велосипед.
Или я где-то промахнулся?
ps. Хотя обход дерева с отбрасыванием вариантов, конечно, более оптимален
Или я где-то промахнулся?grep разве не другую задачу решает?
оставить из входного потока только попадающие под фильтр?
а здесь для каждой строки из входного потока надо сказать каким фильтрам она удовлетворяет.
В моих экспериментах grep (и perl) не проявлял излишнего интеллекта (шаблоны были только префиксными, так что задача была даже проще).
grep - фигуральное выражение о проверке применимости шаблонов приведением их к виду регулярного выражения и использования после этого стандартных библиотек.
grep - фигуральное выражение о проверке применимости шаблонов приведением их к виду регулярного выражения и использования после этого стандартных библиотек.так понятно )
отброс будет идти по первому несовпадению ~= отброс шаблонов в рамках дерева завычетом преобразования integer => string
сколько шаблонов?ты не ответил на один из этих вопросов
сколько строк для обработки?
оцени размер префиксного дерева, если шаблонов 100^9 =)
Вообще, по набору шаблонов можно построить один конечный автомат, который будет разбирать поступающие строки и выдавать каким шаблонам они удовлетворяют за время O(n где n — длина входящей строки. Сам автомат строится не помню за какое время, но если шаблоны статичны, то думаю, что это лучший вариант.
ты не ответил на один из этих вопросовда не, стоко их не будет
оцени размер префиксного дерева, если шаблонов 100^9 =)
давайте так положим
n может быть от 20 до 10000
Вообще, по набору шаблонов можно построить один конечный автомат, который будет разбирать поступающие строки и выдавать каким шаблонам они удовлетворяют за время O(n где n — длина входящей строки. Сам автомат строится не помню за какое время, но если шаблоны статичны, то думаю, что это лучший вариант.о блин
ты примкнул к версии ?
я так понимаю он под грепом ентот автомат и имел ввиду
проблема не в валидации (принадлежность слова к регулярному языку а в нахождении всех путей
Вообще, по набору шаблонов можно построить один конечный автомат, который будет разбирать поступающие строки и выдавать каким шаблонам они удовлетворяют за время O(n где n — длина входящей строки. Сам автомат строится не помню за какое время, но если шаблоны статичны, то думаю, что это лучший вариант.балансированное дерево - это и есть тот самый автомат.
я так понимаю он под грепом ентот автомат и имел ввидуНе уверен, что он именно имел в виду. Но grep, наверняка, тоже автомат делает, наверняка, только он один шаблон ищет, хотя несколько легко объединяются.
В общем, твои шаблоны регулярные, а это прямая дорога к КА. Если только шаблоны не меняются настолько часто, что оверхед на построение автомата будет большой.
Вообще, по набору шаблонов можно построить один конечный автомат, который будет разбирать поступающие строки и выдавать каким шаблонам они удовлетворяют за время O(n где n — длина входящей строки.Только может случиться так, что памяти на его хранение может потребоваться exp(n ну и соотвественно времени на построение, а так ничего
балансированное дерево - это и есть тот самый автомат.Смотря как этим деревом пользоваться.
У автомата есть "циклы", а у дерева нет.
Но автомат стоится из дерева регулярного выражения, на сколько я помню.
вряд ли N*nэто не влияет на асимптотическую сложность в худшем случае
отброс будет идти по первому несовпадению
балансированное деревоИ кстати, какого это оно должно быть балансированное? Тут, на сколько я понимаю, какое получится, такое получится.
И вот что мне придумалось.
Пока входных строк 1 штука, совершенно всё равно как и что сортировать - автомат можно строить как по входной строке
(12|*...
и тогда получать линейное однократное сканирование списка шаблонов,
либо наоборот.
Почему-то мне кажется, что преобразование входной строки к регулярному выражению в данном случае даже более оправдано.
Приколы с существенным выигрышем по операциям начнутся как только нужно будет найти все шаблоны удовлетворяющие одновременно N входным строкам.
Тогда да, обход по дереву, построенному на шаблонах будет давать колоссальный выигрыш по сравнению с линейным сканированием.
ps. И вообще я не понял, откуда у топикстартера взялся log(n) без n впереди. В любом случае файл с шаблонами надо хотя бы прочитать - это уже как минимум n операций.
за время O(nтакое возможно только при малом разбросе величин чисел
т.е. когда набор if-ов можно заменить на косвенную адресацию
более реальная оценка O(n*log(N/n - где n-длина , N-кол-во шаблонов
Только с данными n и N это совершенно по барабану
И кстати, какого это оно должно быть балансированное? Тут, на сколько я понимаю, какое получится, такое получится.берешь дерево которое получилось, и натравливаешь на него алгоритм балансировки => получаешь балансированное дерево
Только может случиться так, что памяти на его хранение может потребоваться exp(n ну и соотвественно времени на построение, а так ничего(где n — длина шаблона но такой расход памяти будет если шаблонов у нас тоже такого порядка, т.е. полный набор. И не факт, что другие методы дадут лучшее потребление при этом.
А вообще это я уже сказал, что такой вариант для случая когда число шаблонов маленькое, а строк большое.
Кстати, мне даже кажется, что маленькое число шаблонов — это далеко не факт, что оно меньше числа строк.
ps. И вообще я не понял, откуда у топикстартера взялся log(n) без n впереди. В любом случае файл с шаблонами надо хотя бы прочитать - это уже как минимум n операций.из того, что за раз обрабатывается одна строка - совсем не следует, что программа перезапускается после каждой обработки одной строки.
соответственно, эффективная структура шаблонов строится один раз на все последующие обработки строк, и этим можно пренебречь.
но такой расход памяти будет если шаблонов у нас тоже такого порядка, т.е. полный набор.Нътъ.
В смысле, не только в этом случае.
Если ты вспомнишь, как строится детерминированный автомат из недетерминированного, то увидишь, где там экспонента.
такое возможно только при малом разбросе величин чиселНу да, предполагаем, что можем хранить большие таблицы, если шаблонов очень много. Думаю, что не стоит заморачиваться Болшими Числами, пока проблема явно не стоит.
т.е. когда набор if-ов можно заменить на косвенную адресацию
более реальная оценка O(n*log(N/n - где n-длина , N-кол-во шаблонов
берешь дерево которое получилось, и натравливаешь на него алгоритм балансировки => получаешь балансированное деревоЭээ... либо я чего-то туплю, либо это из серии отбалансировать дерево разбора программы на каком-либо ЯП. В результате получим кашу.
только минимальным (по кол-ву вершин)
или я торможу ?
мне кажется, что ты путаешь с деревом в узлах которого находятся элементы, которые можно сравнивать
тогда такое дерево можно сбалансировать, чтобы поиск элемента быстро проходил
Нътъ.Ну я сейчас точно не помню, а освежать знания меня ломает. Но там же большинство состояний просто отсеиваются за ненадобностью. А не будут они отсеиваться как раз в том случае, если шаблоны будут разнообразными.
В смысле, не только в этом случае.
Если ты вспомнишь, как строится детерминированный автомат из недетерминированного, то увидишь, где там экспонента.
с деревом в узлах которого находятся элементы, которые можно сравниватьздесь именно такое дерево и стоит строить
Эээ... либо я чего-то туплю, либо это из серии отбалансировать дерево разбора программы на каком-либо ЯП. В результате получим кашу.чего?
чего?В общем правильно написал.
А как ты предлагаешь дерево сравнения делать для шаблонов?
А не будут они отсеиваться как раз в том случае, если шаблоны будут разнообразными.Навскидку мне кажется, что худший случай - это что-то типа
1 * * ... *
* 1 * ... *
...
* * * ... 1
2 * * ... *
...
* * * ... 2
...
...
...
* * * ... k
где n=kN, тогда префиксное дерево должно получиться размером что-то типа N^k, что эквивалентно exp(n так как n>>N
(ну то есть тут можно считерить тоже, но предлагаемый алгоритм не осилит)
Ну да, предполагаем, что можем хранить большие таблицы, если шаблонов очень много. Думаю, что не стоит заморачиваться Болшими Числами, пока проблема явно не стоит.если у тебя числа хотя бы от 1 до 100, то таблица размером 100^9 уже в память не влезет
Ну я сейчас точно не помню, а освежать знания меня ломает. Но там же большинство состояний просто отсеиваются за ненадобностью. А не будут они отсеиваться как раз в том случае, если шаблоны будут разнообразными.Повспоминал немного. Там как раз будет експонента (длина шаблона)^(количество шаблонов но она будет стремиться к максимуму только при больших количествах достаточно разнообразных шаблонов.
А как ты предлагаешь дерево сравнения делать для шаблонов?для разбора следующих шаблонов
*, *, 3
1,*,4
*,2,5
3,1,6
не надо сравнивать первые и вторые числа, а надо сравнивать сразу третье
и общая сложность будет 5 сравнений (3 в худшем на последней цифре + по одному на второй и первой)
и это важное отличие от префиксного дерева, где сравнение всегда идет слева направо.
Навскидку мне кажется, что худший случай - это что-то типаЧего-то сомнительно, что это будет плохой случай. Там же почти линейная структура автомата получается, наверное. Ну даже если он не такой простой, то наверняка не больше, чем (kN)^2.
1 * * ... *
* 2 * ... *
...
* * * ... N
(N+1) * * ... *
...
* * * ... 2N
...
...
...
* * * ... kN
не надо сравнивать первые и вторые числа, а надо сравнивать сразу третьеА у него длина шаблона = длина строки?
и общая сложность будет 5 сравнений (3 в худшем на последней цифре + по одному на второй и третьей)
и это важное отличие от префиксного дерева, где сравнение всегда идет слева направо.
А у него длина шаблона = длина строки?насколько я понял - да, но, в целом, это не важно - идея алгоритма таже останется
идея алгоритма таже останетсяНу тогда например 3-я позиция в шаблоне может соответствовать 3,4,... позиции в строке. Это перебор получится и сложность будет (длина шаблона)*(длина строки). В таком случае, если есть желание, есть алгоритмы, которые позволяют проверить шаблон, проверяя не все символы строки. Я правда не вспомню, можно ли их для нескольких шаблонов параллельно обобщить.
А если длина шаблона строго равна длине строки, то конечно же КА — это излишество уже. Тут можно для построения дерева даже жадные алгоритмы применить, наверное.
Для того, чтобы кол-во операций по шаблонам было k < n, (например, k=log(n нужно, чтобы (n-k) строк вообще не обрабатывались. Как этого добивается топикстартер в случае с
1,2,3,4,5,6,7,8,9
в качестве входной строки и n строк вида
1,2,3,4,5,6,7,8,X
X > 9
в качестве шаблонов?
Где тут будет редуцирование операций?
Линейная составляющая по кол-ву шаблонов в любом случае должна присутствовать.
Если бы у нас была такая ситуация, что мы сравниваем позицию и в зависимости от результата имеем _непересекающиеся_ альтернативы по дальнейшим операциям сравнения, тогда, конечно, да. Здесь можно было бы и балансировать и прочее.
Но тут ситуация другая. В каждом из поддеревьев может быть полный набор оставшихся сравнений. Так что такое дерево тоже потенциально может быть размером (число альтернатив)^(длина шаблона). Тут оптимизация только в том, что такое дерево можно строить быстрее (возможно). Но по памяти оно тоже может быть большим.
да, я стормозил я с экспонентой, скорее может получиться k^N что тоже не сахар при N=9 или даже больше
да, я стормозил я с экспонентой, скорее может получиться k^N что тоже не сахар при N=9 или даже большеУ меня такое чувство, что такие числа будут и в других случаях "структурирования" шаблонов. Да и сами эти шаблоны при таких числах немало места занимать будут.
кстатинет, конечно, надо еще продумать как ходить по этому дереву =)
это первое что мы на доске на работе нарисовали...
чо, реально на этом остановится?
ладно, шучу.
По-моему это идеальный вариант для твоей задачи: перестраивать дерево надо не так уж и часто, тебе надо минимизировать время обработки единичных запросов. Построенное дерево в идеале занимает в памяти примерно столько же (чаще даже меньше) места, чем полный массив Nxn, который все равно надо прочитать. И строится примерно за то же время (с точностью до log (N) множителя
префиксное дерево из шаблонов должно быстро работать
функционирование дерева такое же, как и работа недетерминированного автомата (состояние описывается множеством вершин)
в конечных вершинах (а их ровно столько, сколько шаблонов) имеется ссылка на соответствующий шаблон
сделав 9 шагов по дереву, мы получим состояние, которое содержит только финальные вершины, в которых прописаны искомые шаблоны (сложность проверки, конечно, не 9, но не большая)
очевидно, что это не будет наилучшим решением, однако это будет наилучшим в среднем имхо
есть пути дальнейшей оптимизации:
заметим, что префиксное дерево зависит от порядка символов в шаблонах, а искомая задача - не зависит
то есть применив некую перестановку (речь о математической перестановки из алгебры) к шаблонам и к каждому входному слову, мы получаем эквивалентную задачу, однако префиксное дерево может оказаться кардинально другим
можно из этих деревьев выбирать наиболее оптимальные
например, имея шаблоны (9 заменим на 6)
*, *, *, *, *, 1
*, *, *, *, *, 2
*, *, *, *, *, 3
*, *, *, *, *, 4
для построения оптимального дерева я бы переставил последнее число и первую звездочку. тем самым на первом же шаге (при проходе по префиксному дереву) мы бы отрезали неподходящие варианты
однако не имею представления как сформулировать критерий оптимальности дерева в общем случае и не думаю, что можно существенно что-то ускорить здесь (только если существует специфика шаблонов)
дерево еще хорошо тем, что из него легко удаляется один шаблон и добавляется другой
однако не имею представления как сформулировать критерий оптимальности дерева в общем случае и не думаю, что можно существенно что-то ускорить здесь (только если существует специфика шаблонов)Например такой вариант — чтобы максимальное поддерево после проверки этой позиции содержало минимальное число вершин. Хотя это минимальную длину не гарантирует, но может даже и гарантирует — это надо обдумывать.
Где тут будет редуцирование операций?для такого набора шаблонов строится следующее дерево (балансировка будет только по последней цифре):
для наглядности пусть будет 10 шаблонов, с последней цифрой от 11 до 20
сбалансированное дерево будет
сравнивать последнюю цифру с 15
1) сравнить последнюю цифру с 13
1) сравнить последнюю цифру с 11
1) сравнить первую цифру с 1
1) сравнить вторую цифру с 2
1) сравнить третью цифру с 3
...
2) сравнить последнюю цифру с 14
1) сравнить первую цифру с 1
1) сравнить вторую цифру с 2
1) сравнить третью цифру с 3
...
2) сравнить последнюю цифру с 17
1) сравнить последнюю цифру с 16
1) сравнить первую цифру с 1
1) сравнить вторую цифру с 2
1) сравнить третью цифру с 3
...
2) сравнить последнюю цифру с 19
1) сравнить последнюю цифру с 20
1) сравнить первую цифру с 1
1) сравнить вторую цифру с 2
1) сравнить третью цифру с 3
...
Где тут будет редуцирование операций?соответственно по этому дереву будет задано лишь три вопроса для строки
1,2,3,4,5,6,7,8,9
Если бы у нас была такая ситуация, что мы сравниваем позицию и в зависимости от результата имеем _непересекающиеся_ альтернативы по дальнейшим операциям сравнения, тогда, конечно, да.в дереве у нас есть, как взаимоисключающие варианты, так и нет - ни то, ни другое - балансировку усложняет, но не отменяет.
в дереве у нас есть, как взаимоисключающие варианты, так и нет - ни то, ни другое - балансировку усложняет, но не отменяет.Блин... ты сравнение одной позиции методом дихотомии считаешь балансировкой дерева? (судя по посту выше)
А я дерево описывал в котором в одном узле одно "глобальное" сравнение позиции. И такое дерево не балансируется.
А сравнение одной позиции можно как угодно оптимизировать, но балансировкой я бы называть это не стал.
А я дерево описывал в котором в одном узле одно "глобальное" сравнение позиции. И такое дерево не балансируется.очень плохо, но тоже балансируется: начинать с позиции где меньше всего звездочек, это и есть упрощенная балансировка
очень плохо, но тоже балансируется: начинать с позиции где меньше всего звездочек, это и есть упрощенная балансировкаЭто не балансировка дерева, а алгоритм построения оптимального.
Балансировка — это когда дерево у тебя уже есть, и ты его преобразуешь. При этом узлы сохраняются.
Это не балансировка дерева, а алгоритм построения оптимального.и что не так?
Балансировка — это когда дерево у тебя уже есть, и ты его преобразуешь. При этом узлы сохраняются.
например, шаблоны
1, 2,1
1, 2,2
1, 2,3
1, 2,4
1, 2,5
и т.д.
1, 3,1
1, 3,2
и т.д.
у тебя есть исходное дерево (очень грубо):
1) сравнить первую позицию
1) сравнить вторую позицию
1) сравнить третью позицию
и т.д.
2) сравнить третью позицию
и т.д.
3) сравнить третью позицию
и т.д.
4) сравнить третью позицию
и т.д.
2) сравнить вторую позицию
1) сравнить третью позицию
и т.д.
2) сравнить третью позицию
и т.д.
3) сравнить третью позицию
и т.д.
4) сравнить третью позицию
и т.д.
3) сравнить вторую позицию
1) сравнить третью позицию
и т.д.
2) сравнить третью позицию
и т.д.
3) сравнить третью позицию
и т.д.
4) сравнить третью позицию
и т.д.
4) сравнить вторую позицию
1) сравнить третью позицию
и т.д.
2) сравнить третью позицию
и т.д.
3) сравнить третью позицию
и т.д.
4) сравнить третью позицию
и т.д.
ты на него смотришь и видешь, что если сравнения поменять местами, то дерево уменьшится:
1) сравнить третью позицию
1) сравнить вторую позицию
1) сравнить первую позицию
2) сравнить вторую позицию
1) сравнить первую позицию
3) сравнить вторую позицию
1) сравнить первую позицию
4) сравнить вторую позицию
1) сравнить первую позицию
и т.д.
соответственно - это и есть алгоритм балансировки - перестроение исходного дерева
соответственно - это и есть алгоритм балансировки - перестроение исходного дереваПри балансировке число узлов и они сами не меняются. Меняется глубина.
При балансировке число узлов и они сами не меняются. Меняется глубина.т.е. ты хочешь сказать, что вот это "число узлов и они сами не меняются" - является сутью термина "балансировка"?
и если это нарушается, то термин "балансировка" использовать нельзя, а нужно использовать какой-то другой термин? какой?
Ну фактически ты строишь новое дерево. А термин "балансировка" всё же прижился в другом контексте, хотя может это только в моём сознании так. В общем мы только в терминологии не сходимся.
Ну фактически ты строишь новое дерево. А термин "балансировка" всё же прижился в другом контексте, хотя может это только в моём сознании так. В общем мы только в терминологии не сходимся.я не строю новое дерево, я именно балансирую старое - и узлы новые кстати не появляются, лишь либо схлопываются, либо дублируются
классическая балансировка описывается для операция сравнения которая определена между любыми двумя парами, в данной задаче - операция сравнения "рванная" - лишь некоторые пары сравнимы - из-за этого при балансировке происходит либо дублирование подузлов когда узел опускается, либо схлопывание продублированных, когда узел поднимается.
Составить 9 разбиений всех шаблонов на категории, каждая категория отвечает за одну позицию в шаблоне, если числа от 1 до 100, то по 99 категорий в разбиении. Каждой строке будет соответсвовать по одной категории из этих 9 разбиений, взяв пересечение этого множества получим все шаблоны. Пересечение упорядоченых масивов делать легко, принадлежность к категории тоже легко определить.
взяв пересечение этого множества получим все шаблоныкак это сделать быстро?
Довольно просто, каждое множество - упорядоченый массив, проходишь по одному из них сравнивая с остальными, т.к. они упорядочены, достаточно одного прохода по всем массивам 9-ю итераторами.
девятью итераторами имхо трудновато будет. Все равно придется попарно сливать, нет?
N*n*log(M) получается, худший случай - когда почти везде звёздочки - списки будут длинными
где M=N, или я невнимательно тред прочитал?
А, нашел. M — максимальное число? Причем тут оно в этом решении?
оно тут при том, что "100 категорий в каждом разбиении"
Я понял его идею так: 9 раз сортируем массив шаблонов по каждому столбцу в отдельности. Потом по числу в очередной позиции входной строчки несложно получаем упорядоченную последовательность номеров подходящих образцов, сливаем. Но это то же самое, что и дерево, чуть медленнее.
либо дублируютсяВ процессе дублирования как раз новые узлы появляются.
И кстати, ведь у тебя должна быть возможность перейти от отсутствующего сравнения позиции к её наличию, т.к. твои процедуры должны порождать весь класс эквивалентных деревьев. Что дублировать в этом случае надо?
Но это то же самое, что и дерево, чуть медленнее.Я бы сказал, это то же тупое сравнение, но вид сбоку.
Но с деревом тоже не стоит сильно искушаться: ответ — это подмножество шаблонов, размер которого дает довольно жесткое ограничение на сложность.
девятью итераторами имхо трудновато будет. Все равно придется попарно сливать, нет?
9 итераторами просто
Берешь первые 9 значений, находишь максимум и минимум, если не равны, все что меньше максимума начинаешь продвигать дальше по масиву, пока не станут больше равны, получаешь новый максимум, старый максимум становится минимумом, когда минимум с максимумы равны - это искомое значение, все масивы проходишь один раз, дла каждого продвижения по масиву используется одно сравнение с текущим максимумом.
Тред нечетал, минимальные ацикличные автоматы упоминались?
А, ну я тоже не понял причем тут категории.
Я понял его идею так: 9 раз сортируем массив шаблонов по каждому столбцу в отдельности. Потом по числу в очередной позиции входной строчки несложно получаем упорядоченную последовательность номеров подходящих образцов, сливаем. Но это то же самое, что и дерево, чуть медленнее.
Не совсем так, я имел ввиду хранить 9х100 упорядоченых масивов, каждый массив соответсвует позиции и числу или звездочке, при добавлении шабшлона мы добавляем его номер в те масивы, к которым он подходит, т.е в случае * во все масивы для данной позиции, либо в один конкретный (можно завести отдельный масив для * и класть туда, тогда надо будет искать пересечение 18 масивов).
Для строчки берем 9 конкретных подходящих для нее масива и пересекаем.
А что за 100?
Я бы сказал, это то же тупое сравнение, но вид сбоку.
Да сравнение, но не тупое
изначально шаблоны кидаем в структуру с быстрой выбиркой (дерево или даже хешсет)решение, имеющее право на жизнь
с поданной строкой составляются всевозможные шаблоны
т.е. 1,2,3,* и 1,2,*,4 и 1,2,*,* и т.д.
т.е. всего их 2^N
дальше все их проверяем есть ли такие, ну тойсть отфильтровываем, т.е. типа 2^N * log(n где n - число шаблонов
1) шаблоны упорядочены (лексикографически, * меньше любого числа)
2) для входного слова (a1, a2, ...aN) определяем множество всех шаблонов (их будет 2^N)
упорядочиваем их
3) считаем intersection двух множеств - это и есть искомый результат
сложность операции 1) - n*log(n)
сложность операции 2) - const(N)
сложность операции 3 как уже выше писали n + 2^N (в худшем случае)
для n = 10000, N = 9 это может быть вполне неплохо
поясню операцию 2 - при фиксированном N _порядок_ этих самых шаблонов на самом деле не зависит от входного слова. поэтому 2^N шаблонов можно сгенерить и упорядочить в самом начале (либо завести умный итератор, который в правильном порядке будет обходить эти шаблоны)
числа ну скажем ограничены 100, т.е. всего различных строк-шаблонов 100^9
Ну вот это очень плохо, имхо. Т.е. это с тем же успехом можно сказать, что массивы надо всегда сортировать подсчетом: пусть только количество различных чисел будет 50.
to и : так вы помните, что слияние списков очень затратная операция в плане константы (которая идет перед оценкой сложности): для каждого списка же надо память выделить, потом прибить и т.д.?
to и : так вы помните, что слияние списков очень затратная операция в плане константы (которая идет перед оценкой сложности): для каждого списка же надо память выделить, потом прибить и т.д.?
Где ты увидел слияние списка?
Где ты увидел слияние списка?
считаем intersection двух множеств
Это было в условии задачи, если числа не ограничены небольшим числом, то нужно реализовывать по другому.
А, прощу прощения
Слияние и пересечение это разные вещи.
Слияние и пересечение это разные вещи.т.е. выделение памяти не будет?
Слияние и пересечение это разные вещи.если по занудствовать, то пересечение - это частный случая слияния.
А если занудствовать, то есть правила Де-Моргана. Так-то.
А если занудствовать, то есть правила Де-Моргана. Так-то.как они здесь применимы?
Ну типа пересечение не сложнее объединения. Объединение не сложнее пересечения.
to и : так вы помните, что слияние списков очень затратная операция в плане константы (которая идет перед оценкой сложности): для каждого списка же надо память выделить, потом прибить и т.д.?я не вижу много затрат при подсчете пересечения двух множеств
результат пересечения - это список ссылок (указателей, на прогр. языке) на элементы уже существующих множеств (или одного из множеств, это ведь пересечение)
оффтоп: списки отстой, вектор + указатели рулят =)
это список ссылокс динамическим выделением памяти?
типа пересечение не сложнее объединения. Объединение не сложнее пересечения.это не морган
512 указателей хватит
да и вообще тебя понесло не туда=) спички считаешь)
гораздо больше потерь будет при конвертации строки "a1, a2, , a9" в набор чисел =)
гораздо больше потерь будет при конвертации строки "a1, a2, , a9" в набор чисел =)допустим шаблонов тысяч 9,
хочешь сказать что слить 9 раз списки размером тысяча каждый, это дольше чем распарсить строку длиной 40 символов?
сливаться-то списки будут на каждую входную строчку, а не один раз предварительно.
http://ru.wikipedia.org/wiki/Законы де Морганадля танкистов, покажи, пожалуйста, полностью логическую цепочку (т.е. как связаны мой пост, твой пост с двумя отрицаниями и законы моргана)
вместо исходных массивов сразу получаем дополненные, это не увеличивает сложность. Дальше вместо пересечений реализуем дополнение, либо наоборот. Дополнение полученного массива делается в один проход — явно не сложнее, чем все остальное.
Ну типа пересечение не сложнее объединения. Объединение не сложнее пересечения.честно говоря, я тоже не понял как ты из законов де Моргана сделал вывод о сложности соответствующих операций =)
по-моему, надо изучить сложность операции "дополнение" для начала=)
Но это странно: рассуждать о сложности объединения и пересечения в сравнении с дополнением.
вместо исходных массивов сразу получаем дополненныечто такое дополненные массивы?
Наверное стоит удалить все, что я писал выше =)
Я тут подумал, что если использовать вместо упорядоченых масивов битовые поля, то сэконмится память и увеличится быстродействие, взять пересечение битовых полей - элеметарная операция.
В общем так: предлагаю написать оба варианта и потестить скорость на настоящих данных.
Хотя про память может и наврал, чет не соображаю после работы
Можно, но пока не знаю как со временем будет.
Ну вообще этим бы топикстартеру в самую пору заняться.
Оставить комментарий
pitrik2
из файла считываются строки-шаблоны, на вход подается строка, нужно быстро уметь получать все шаблоны которым поданная строка удовлетворяетстроки-шаблоны все одинаковой длины N (щас это 9, может будет больше потом строка-шаблон это N ячеек, в каждой ячейке либо число либо звездочка, звездочка означает что тут любое число
примеры строк-шаблонов:
числа ну скажем ограничены 100, т.е. всего различных строк-шаблонов 100^9
поданная строка содержит только числа
т.е. если строка 1,2,3,4
то она удовлетворяет 1,2,3,4 и 1,2,3,* и *,*,*,* но не удовлетворяет 5,2,3,* и *,*,3,25
вот пример алгоритма (кажись он медленный):