Как найти позицию вхождения одного вектора во второй

147
14 декабря 2021, 04:30

Условия:

  1. Вектор A всегда больше вектора B
  2. Вектор B входит в вектор A
  3. Вектор A очень большой, в отличие от вектора B

Нужно:

Найти позицию вхождения одного вектора в другой

Answer 1

Для решения в Вашей задачи (в не отсортированной коллекции) возьмите std::search

Пример кода :

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>

int main() {
    std::vector<int> base(10'000'000);
    std::iota(std::begin(base), std::end(base), 0);
    std::rotate(std::begin(base), std::begin(base) + (base.size() / 2) , std::end(base));
    std::vector<int> a(15);
    std::iota(std::begin(a), std::end(a), 777);
    std::vector<int> b(15);
    std::iota(std::begin(b), std::end(b), -777);
    auto res_1{std::search(std::begin(base), std::end(base), std::default_searcher(std::begin(a), std::end(a)))};
    if (res_1 != std::end(base)) {
        std::cout << "sequence found" << std::endl;
    } else {
        std::cout << "sequence not found" << std::endl;
    }
    auto res_2{std::search(std::begin(base), std::end(base), std::default_searcher(std::begin(b), std::end(b)))};
    if (res_2 != std::end(base)) {
        std::cout << "sequence found" << std::endl;
    } else {
        std::cout << "sequence not found" << std::endl;
    }
    return 0; 
}

Тут вся соль именно в механизме сравнение подпоследовательности, в примере я написал std::default_searcher но есть еще

default_searcher
(C++17)
standard C++ library search algorithm implementation
(class template)
boyer_moore_searcher
(C++17)
Boyer-Moore search algorithm implementation
(class template)
boyer_moore_horspool_searcher
(C++17)
Boyer-Moore-Horspool search algorithm implementation
(class template)

Все о них есть тут https://en.cppreference.com/w/cpp/utility/functional

Answer 2

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

Часто эта структура используется в биоинформатике, как раз с теми же условиями – огромные размеры исходного массива, заметно меньшие у искомого. У префиксного дерева есть реализации с оптимизациями для сжатия размера.

Полезные ссылки:

  • Описание на Хабре

  • Описание и пример реализации на GeeksForHeeks

Нужно найти позицию вхождения одного вектора в другой

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

Answer 3

Если искомый вектор маленький или вероятность частичного его совпадения с куском основного не слишком велика, то я бы использовал самый тупой алгоритм: перебираем первый символ вектора A и пытаемся начиная с него накладывать вектор B и сравнивать до тех пор, пока вектор не закончится или пока не будет найдено различие. В худшем случае работать будет за произведение длин, но такие данные надо подбирать намеренно.

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

READ ALSO
Ввести порядковый нoмер игральной карты от(0 до 35) и определить масть и достоинство карты(не надо писать 36 if или switch)

Ввести порядковый нoмер игральной карты от(0 до 35) и определить масть и достоинство карты(не надо писать 36 if или switch)

Написала с 36 свитчами,нельзя использовать цикл и тдНужно ограничаться ифами и свитчами,буду рада помощи

110
SendMessage всем окнам с определенным классом

SendMessage всем окнам с определенным классом

Допустим у меня есть 3 запущенных параллельно окна с одним и тем же классомПри клике в одном из них я хочу отсылать с помощью SendMessage информацию...

76
Qt C++ QComboBox Palette - установка цвета (background-color)

Qt C++ QComboBox Palette - установка цвета (background-color)

Как без использования styleSheet изменить background-color QComboBox ? Используя вот такой код:

172
Метод, считывающий данные из потока ввода и возвращающий char[n]

Метод, считывающий данные из потока ввода и возвращающий char[n]

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

80