|
1 / 1 / 0
Регистрация: 01.11.2019
Сообщений: 31
|
|
Проблема в оптимизации алгоритма (Нахождение подстрок в строке, работа с большими данными)04.11.2023, 22:32. Показов 2563. Ответов 30
Решаю задачу и не могу сдвинуться с места. Подскажите пожалуйста, куда думать.
В общем задача: У меня есть строка S длиной n. Я должен сформировать подстроку R из k последних элементов этой строки и найти наиболее часто встречающейся элемент в строке S, который идет после подстроки R. Полученный элемент я добавляю в конец строки S. Такие действия я должен проделать очень много раз. Если после подстроки нету символов, то добавляется 'a'. Ограничения: S - строка из букв английского алфавита('a'-'z'). k<n<a<b, b<10^18, 2<=n<=10^6, 1<=k<n, b-a+1<=10^6 В итоге я должен вывести элементы увеличенной строки S начиная с a-тей позиции до b-тей позиции включительно, то есть элементов будет ровно b-a+1. Например, для входных данных(n, k, a, b): 6 1 7 10 qwertq Ответом будет: wert. Строка после действия:1) qwertqw, 2)qwertqwe, 3)qwertqwer, 4) qwertqwert. У меня пока что идея такая: Использовать алгоритм Кнута-Морриса-Пратта для поиска подстрок из k-последних символов начальной строки. Найти наиболее встречающейся символ и добавить его в конец изначальной строки S. И так проделать от n до b. Но b может быть слишком большое(10^18) и если b хотя бы 10^8, уже проблемы. Сегодня утром пришла идея: провести 52 операции с добавлением новых символов в конец строки S, потом найти образец повторяющейся подстроки в строке S, т.к. случае с большим b, все, что идет после[S.size()] в строке S по идее будет зациклено этим образцом. Но что дальше делать с этим образцом, я уже без понятия. Пробовал как-то работать с остатком от деления по индексам, но все равно нахожу случаи с неверным ответом. Куда думать в этой задаче, я уже без понятия.
0
|
|
| 04.11.2023, 22:32 | |
|
Ответы с готовыми решениями:
30
Нахождение подстрок в строке Работа с большими данными Работа с большими данными |
| 05.11.2023, 15:50 | ||
|
Ладно, пытаюсь читать дальше. Но приводимый Вами пример еще более непонятен. И начинать (мучительные) выяснения в чем собсно задача - никакого желания нет. Подумайте как сформулировать задачу чтобы она (возможно) вылилась в интересное/плодотворное обсуждение, а не отягощала форум
0
|
||
|
1 / 1 / 0
Регистрация: 01.11.2019
Сообщений: 31
|
||||||
| 05.11.2023, 17:28 [ТС] | ||||||
|
Полная формулировка задания.
Вася обнаружил в себе страсть к машинному обучению. В настоящее время он работает над проектом новой языковой модели, которую он назвал ChatGPT. Модель на входе получает n-буквенное слово S и параметр k (целое число 1 ≤ k < n), а затем генерирует продолжение слова. Предположим , у нас уже есть слово S', которое является расширением S некоторыми буквами. Добавление новой буквы будет выглядеть следующим образом (см. Также пример ниже): мы рассматриваем K-буквенный суффикс R слова S 'и смотрим на все предыдущие вхождения R в слове S' (как последовательное подслово). Затем для каждой буквы из алфавита мы подсчитываем, сколько раз она появлялась непосредственно после R в слове S'. Пусть c-буква, которая встречается чаще всего. Мы решаем ничьи в пользу буквы, ранее встречавшейся в алфавите , и если R не встречается где-либо еще в слове S', Мы имеем c = 'a'. в конце мы расширяем слово S', добавляя в его конце букву c. например, пусть S = abaaabababa и k = 3. У нас есть S ' = S, R = aba и R встречается раньше со следующей буквой как: abaa, abab, abab. Чаще всего встречается с буквой b, поэтому к S ' мы добавляем b. Теперь S '= abaaabababab, R = bab а также R встречается раньше со следующей буквой как baba, baba, поэтому мы добавляем к S' 'a'. Ваша задача-написать программу, которая будет реализовывать модель, разработанную Василием. Вход В первой строке ввода четыре целых числа n, k, a и b (2 ≤ n ≤ 10^6 , 1 ≤ k < n, n < a < b < 10^18 , b + 1 − a ≤ 10^6 ). Во второй строке ввода находится n-буквенная строка, состоящая из строчных букв английского алфавита ('a' - 'z'), обозначающая слово S. Выход На вывод следует вывести строку b+1-a, обозначающую буквы в расширенном слове S' в позициях от а-й до b-й (включительно). Другими словами, мы предполагаем, что к исходному слову S было добавлено b-n букв, и мы хотим вывести последние b+1-a из этих добавленных букв. Пример Для ввода: 11 3 12 13 abaaabababa Ответ: ba Как пытаюсь решать я, но почему-то не выходит. Определенное кол-во раз выполняю алгоритм КМП для поиска всех вхождений подстроки в строку, нахожу самый часто встречающейся элемент в данной строке после подстроки, добавляю этот элемент в строку и так 1000 раз. После, беру последний элемент строки и нахожу зацикливание как-то так:
Потом вычисляю по формуле, сколько мне нужно прибавить к индексу нулевого элемента(jt), чтобы получить элемент с позицией a-1. количество_элем*i + индекс_нулевого_элем + количество_элем = a. => i=(a-jt-start_otl)/start_otl. где i - перебирается циклически с 0 до start_otl. По идее должно работать, но при больших n(около 10^5*2) и с множеством разных букв, выполняется долго(30 сек.) и иногда выводит неправильный ответ. Добавлено через 20 минут Igor3D, Сформировать, то есть добавлять новые элементы в исходную строку. Пример: 6 1 7 10 qwertq Я из этой строки беру суфикс размером с 1, тоесть 'q'. После, нахожу наиболее встречающейся символ в исходной строке после суфикса q, то есть 'w' и его добавляю в конец исходной строки. Получаю qwertqw и снова беру суфикс размером с 1, то есть 'w'. Делаю тоже самое, поучаю элемент 'e' и добавляю в конец строки. Получаю qwertqwe и так далее до позиции b-1. В итоге вывожу подстроку с элементами начиная од индекса a-1, заканчивая индексом b-1 включительно. Ответ: wert.
0
|
||||||
|
|
||||||
| 06.11.2023, 00:02 | ||||||
|
Идея оптимизировать: для любой подстроки самый частый символ идущий после неё так и останется самым частым так как именно он и будет добавляться после неё, поэтому не надо искать его каждый раз, достаточно найти его один раз и запомнить. Работать прога должна быстро. Что касается потребления памяти то при небольших k различных подстрок будет немного так что памяти займёт немного. А вот при больших k - вопрос.
1
|
||||||
| 06.11.2023, 14:27 | ||
|
Не по теме:
Конечно это не тот ответ что "сильно поможет", но другого здесь может и не быть
0
|
||
|
1 / 1 / 0
Регистрация: 01.11.2019
Сообщений: 31
|
||
| 06.11.2023, 21:15 [ТС] | ||
|
Igor3D, Здесь прикол в том, что я изначально использовал алгоритм Кнута-Морриса-Пратта за время O(N+M), вроде бы ок, но если входная строка 10^6 и очень замудренная(например огромный, логичный текст), то непонятно за сколько таких проходов КМП я узнаю первый индекс цикличной подстроки(которая в дальнейшем будет повторятся). На сколько я понимаю, составители этой задачи хотят не больше O(200(N+M)), а как это оптимизировать, я без понятия.
Добавлено через 9 минут igorrr37, Не совсем понял. По идее мы должны всегда искать самый частый символ, т.к. строка обновляется и собственно подстрока тоже. Например: 6 1 7 10 qwertq Подстрока 'q' с индексом 5. Ищем ее в строке 'qwertq', нашли на позиции 0, после нее идет 'w' и нашли на позиции 5, после нее нет ничего. Наиболее встречающейся символ 'w' добавляем в конец, получаем строку 'qwertqw'. Опять берем подстроку с конца, размером 1 - это 'w'. Проделываем то же самое, находим самый частый символ - 'e' и добавляем в конец. Такие действия нужно проделать до b-1, то есть увеличить строку до девятого индекса(с размером =b=10). b - может быть 10^18-1. Добавлено через 6 минут
0
|
||
| 07.11.2023, 05:55 | |
|
Похоже из алгоритмов "быстрого поиска" ничего не выжать. Так или иначе они прожевывают всю (потенциально огромную) строку, поэтому выигрыш (по сравнению с прямым поиском) не так уж велик. Нужно делать упор на то что (последовательно) ищутся подобные/близкие строки, и результаты предыдущего поиска могут быть использованы для последующего. Есть простой способ это сделать. Пример
Пусть искомая подстрока "abcd". В исходной строке найдем позиции всех "cd" (вторя половина искомой). Это будет относительно небольшой вектор int. Просматривая его можно найти все подстроки "abcd", "bcd?", "cd??" где ? - любой новый добавленный символ. Правда когда вытеснено "c" - ничего не попишешь, придется опять месить всю строку собирая новый вектор. Ну и надо "подсматривать" стартовые и/или конечные буквы в исходной строке, читается лишь ее небольшая часть но "вразнобой", сбивается кеш. Для искомой длиной 1 или 2 это не годится, нужен прямой поиск. Для длин 3 или 4 вероятно эффект невелик или отрицательный (расходы на создание вектора). А вот с увеличением длины искомой КПД/эффективность быстро растет. Реализация несложна, но требует "прямизны рук"
1
|
|
|
698 / 574 / 75
Регистрация: 20.09.2014
Сообщений: 3,710
|
|
| 07.11.2023, 06:35 | |
|
a = n + 1,
b = n + 1 + m, где m - это число символов, которые надо добавить в строку S. Зачем усложнять задачу этими a и b? Из-за этого и есть путаница во всем. Если алгоритм не работает правильно, значит он неправильно реализован.
0
|
|
|
|
||
| 07.11.2023, 10:01 | ||
|
0
|
||
|
Модератор
3134 / 2281 / 469
Регистрация: 26.03.2015
Сообщений: 8,878
|
||||||
| 08.11.2023, 21:39 | ||||||
|
В данной задаче поиск подстроки вообще не нужен. Один раз проходим по строке, подсчитывая частоту символов после каждой подстроки заданной длины. Затем частоту символов заменяем на самый частый. По этой таблице (подстрока - символ) можно построить всю строку до нужной позиции.
1
|
||||||
| 09.11.2023, 13:02 | ||
|
Вот есть строка "абвгдеж..", ищется какая-то подстрока длиной 4. Помещаем "абвг" в хеш/словарь, потом "бвгд", "вгде" и.т.д., в итоге имеем словарь "на все случаи жизни". Если так то: словарь может оказаться слишком велик. Да и вызов Substring и TryGetValue для такой кратности - не верю
0
|
||
|
698 / 574 / 75
Регистрация: 20.09.2014
Сообщений: 3,710
|
|
| 09.11.2023, 18:31 | |
|
Если у нас начало слова "alph", то последующие буквы можно сразу выдать пачкой "a" или "abet", т.е. слово целиком - "alpha" или "alphabet". Каждая буква таких слов будет частая.
Добавлено через 1 минуту Но я задачу нифига не понимаю. Число k фиксированное или изменяется в процессе?
0
|
|
|
Модератор
3134 / 2281 / 469
Регистрация: 26.03.2015
Сообщений: 8,878
|
|||||
| 10.11.2023, 00:00 | |||||
|
0
|
|||||
| 10.11.2023, 12:34 | ||
|
0
|
||
|
1 / 1 / 0
Регистрация: 01.11.2019
Сообщений: 31
|
||||||
| 14.11.2023, 10:39 [ТС] | ||||||
|
В общем шляпа. На входных данных, близких к ограничениям считает быстро. 20 000 новых символов находит за 2 сек. Но попадаються такие тесты, где скорее всего колизия выскакивает (не находит хеш в unordered_map, хотя должен). Что с ней делать я без понятия. При увиличении переменных p и m, увеличивается кол-во найденных символов, но это такое себе.
Код на плюсах. Сначала заполняю patterns хешами, буквами и количеством для каждой буквы. После этого, заполняю pats(хеш и самая частая буква). Дальше прохожу 20к итераций постепенно прибавляя найденные символы в конец строки, тем самым обновляя pats. После этого в планах найти циклическую подстроку и сгенерировать ответ(вроде понимаю как это сделать). Но например для входных данных: (n,k,a,b) 1000000 23919 129765611 130373173 рандомные_буквы Перед основным циклом(поиска новых букв), в pats 454197 УНИКАЛЬНЫХ ключей. И каким образом в строке 10^6 букв может быть столько ключей при k=23919? При больших k и n=10^6, работает шустро и находит 2ляма новых символов за 1 сек. Может в коде намудрил, я не знаю. Как решить проблему?
Пробовал и такое, при больших k, иногда словарь заполняет долго(20 сек.) иногда быстро (2-3 сек). Добавлено через 7 минут Думаю за 5 сек. не вытянет. Наткнулся на тест, где нужно было найти около ляма новых букв. В ответе на тест было 2 огромных цикличных подстроки. Добавлено через 3 минуты k - фиксированное, каждый раз берется подстрока из k последних символов входной строки, находится самая частая буква после подстроки во входной строке и добавляется в конец входной строки и т.д. Добавлено через 4 минуты Попробовал, все тесты в теории проходит, кроме n=10^6 и k до +-30000. Если k большое, находит 1 лям новых символов очень быстро(до 1 сек.).
0
|
||||||
|
1 / 1 / 0
Регистрация: 01.11.2019
Сообщений: 31
|
|
| 14.11.2023, 17:14 [ТС] | |
|
Shamil1, Пробовал и такое, при больших k, иногда словарь заполняет долго(20 сек.) иногда быстро (2-3 сек).
Добавлено через 1 минуту Igor3D, Думаю за 5 сек. не вытянет. Наткнулся на тест, где нужно было найти около ляма новых букв. В ответе на тест было 2 огромных цикличных подстроки. Просмотрев тесты, составители задачи видимо хотят поиск за O(1). Добавлено через 26 секунд Mikhaylo, k - фиксированное, каждый раз берется подстрока из k последних символов входной строки, находится самая частая буква после подстроки во входной строке и добавляется в конец входной строки и т.д. Добавлено через 51 секунду igorrr37, Попробовал, все тесты в теории проходит, кроме n=10^6 и k до +-30000. Если k большое, находит 1 лям новых символов очень быстро(до 1 сек.).
0
|
|
| 15.11.2023, 14:34 | ||
|
Владислав2313, если прозвучало "большие данные", то мы не можем надеяться даже на то что строка вся/целиком сядет в память (а не пойдет по свопам). Не говоря уже о таком дорогом удовольствии как ассоциативной контейнер. Тем более "контейнер на контейнер". Вот для определения зацикливания - там да, используйте что угодно. Но не для поиска.
0
|
||
|
|
||
| 15.11.2023, 19:52 | ||
|
Я может быть неправильно все понял, но попробую описать, что мне кажется нужно проделать. 1. С помощью КА пробегаем по строке и находим позиции подстроки. Кладем в массив или вектор. 2. Зная длину подстроки определяем самый частый символ - и добавляем его в конец. 3. Удаляем из массива те индексы, в которых этого символа в нужной позиции нет. 4. Инкрементим позиции в массиве. 5. Повторяем начиная с п.2 нужное количество раз. Добавлено через 7 минут Если допустимы перехлёсты - то КА придется откатывать на следующий символ от начала найденной подстроки.
1
|
||
|
1 / 1 / 0
Регистрация: 01.11.2019
Сообщений: 31
|
||
| 15.11.2023, 20:29 [ТС] | ||
|
Добавлено через 1 минуту vantfiles, С КА еще не работал. Почитаю что это такое.
0
|
||
| 15.11.2023, 20:29 | |
|
Помогаю со студенческими работами здесь
20
Работа с большими данными
Работа с большими данными (30-40tb) Советы по оптимизации роботы с большими массивами. Работа с данными в строке Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога
Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
|
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога
Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
|
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
|
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога
Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
|
|
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога
Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
|
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога
Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
|
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
|
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога
В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
|