|
1 / 1 / 0
Регистрация: 01.11.2019
Сообщений: 31
|
|
Проблема в оптимизации алгоритма (Нахождение подстрок в строке, работа с большими данными)04.11.2023, 22:32. Показов 2660. Ответов 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
|
|
|
691 / 575 / 75
Регистрация: 20.09.2014
Сообщений: 3,751
|
|
| 07.11.2023, 06:35 | |
|
a = n + 1,
b = n + 1 + m, где m - это число символов, которые надо добавить в строку S. Зачем усложнять задачу этими a и b? Из-за этого и есть путаница во всем. Если алгоритм не работает правильно, значит он неправильно реализован.
0
|
|
|
|
||
| 07.11.2023, 10:01 | ||
|
0
|
||
|
Модератор
3137 / 2284 / 469
Регистрация: 26.03.2015
Сообщений: 8,888
|
||||||
| 08.11.2023, 21:39 | ||||||
|
В данной задаче поиск подстроки вообще не нужен. Один раз проходим по строке, подсчитывая частоту символов после каждой подстроки заданной длины. Затем частоту символов заменяем на самый частый. По этой таблице (подстрока - символ) можно построить всю строку до нужной позиции.
1
|
||||||
| 09.11.2023, 13:02 | ||
|
Вот есть строка "абвгдеж..", ищется какая-то подстрока длиной 4. Помещаем "абвг" в хеш/словарь, потом "бвгд", "вгде" и.т.д., в итоге имеем словарь "на все случаи жизни". Если так то: словарь может оказаться слишком велик. Да и вызов Substring и TryGetValue для такой кратности - не верю
0
|
||
|
691 / 575 / 75
Регистрация: 20.09.2014
Сообщений: 3,751
|
|
| 09.11.2023, 18:31 | |
|
Если у нас начало слова "alph", то последующие буквы можно сразу выдать пачкой "a" или "abet", т.е. слово целиком - "alpha" или "alphabet". Каждая буква таких слов будет частая.
Добавлено через 1 минуту Но я задачу нифига не понимаю. Число k фиксированное или изменяется в процессе?
0
|
|
|
Модератор
3137 / 2284 / 469
Регистрация: 26.03.2015
Сообщений: 8,888
|
|||||
| 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) Советы по оптимизации роботы с большими массивами. Работа с данными в строке Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
| Опции темы | |
|
|
Новые блоги и статьи
|
|||
|
Валидация и контроль данных табличной части документа перед записью
Maks 22.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в КА2.
Задача: контроль и валидация данных табличной части документа перед записью с учетом регламента компании. . .
|
Отчёт о затраченных материалах за определенный период с макетом печатной формы
Maks 21.04.2026
Отчёт из решения ниже размещён в конфигурации КА2.
Задача: разработка отчёта по затраченным материалам за определённый период, с возможностью вывода печатной формы отчёта с шапкой и подвалом.
В. . .
|
Отчёт о спецтехнике находящейся в ремонте
Maks 20.04.2026
Отчёт из решения ниже размещен в конфигурации КА2.
Задача: отобразить спецтехнику, которая на данный момент находится в ремонте.
Есть нетиповой документ "Заявка на ремонт спецтехники" который. . .
|
Памятка для бота и "визитка" для читателей "Semantic Universe Layer (Слой семантической вселенной)"
Hrethgir 19.04.2026
Сгенерировано для краткого описания по случаю сборки и компиляции скелета серверного приложения. И пусть после этого скажут, что статьи сгенерированные AI - туфта и не интересно. И это не реклама -. . .
|
|
Запрет удаления строк ТЧ документа при определённом условии
Maks 19.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "Аккумуляторы", разработанного в конфигурации КА2. У данного документа есть ТЧ, в которой в зависимости от прав доступа. . .
|
Модель заражения группы наркоманов
alhaos 17.04.2026
Условия задачи сформулированы тут
Суть:
- Группа наркоманов из 10 человек.
- Только один инфицирован ВИЧ.
- Колются одной иглой.
- Колются раз в день.
- Колются последовательно через. . .
|
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
|
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
|