Я хотел бы пересечь более двух массивов. Вот неполная версия моей кодировки:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    int n;

    cin >> n;
    cout << "\n";

    string rock[n];

    for(int i=0;i<n;i++)
    {
        cin >> rock[i];
        cout << "\n";
    }

    for(int i=0;i<n;i++)
        sort(rock[i].begin(), rock[i].end());

}

Так, например, если я ввожу

3
asasadfg
aassdw
dasaasf

Я хочу, чтобы вывод был таким

ads

Нет дублирования и пересечения между более чем 2 массивами. Как лучше всего это сделать? Спасибо

c++
2
Yasamura 4 Фев 2022 в 04:54
2
A ∩ B ∩ C равно ( A ∩ B ) ∩ C, поэтому вы можете вычислить пересечение двух массивов, а затем получить третий. Вы можете использовать std::set_intersection() для этого
 – 
Slava
4 Фев 2022 в 05:24

2 ответа

Примечание. Массивы переменной длины не являются стандартными в C++ и в лучшем случае являются функцией, специфичной для компилятора. В этом случае, поскольку длина неизвестна во время компиляции, лучше всего использовать std::vector.

Теперь нам просто нужно знать, как найти пересечение двух строк и сделать это по всему вектору. Я уверен, что есть более элегантный способ, но, надеюсь, вы сможете проследить, что происходит ниже.

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>

int main() {
    int n;

    std::cin >> n;
    std::cout << "\n";

    std::vector<std::string> rocks;

    for (int i = 0; i < n; ++i) {
        std::string temp;
        std::cin >> temp;
        rocks.push_back(temp);
        std::cout << "\n";
    }

    for (auto &s : rocks) {
        std::sort(s.begin(), s.end());
    }

    std::string diff = rocks[0];

    for (int i = 1; i < n; ++i) {
        std::string temp_diff;

        std::set_intersection(
            diff.begin(), diff.end(), 
            rocks[i].begin(), rocks[i].end(),  
            std::back_inserter(temp_diff));

        diff = temp_diff;
    }

    auto last = std::unique(diff.begin(), diff.end());
    diff.erase(last, diff.end());

    std::cout << diff << std::endl;

    return 0; 
}
2
Chris 4 Фев 2022 в 05:23
Я не очень хорошо разбираюсь в авто и векторе, поэтому я проверил весь код, и в результате появилось несколько ошибок, таких как «|21|ошибка: определение функции не разрешено здесь перед токеном ':'|», «|25 |ошибка: не удалось преобразовать diff' to bool'|", "|27|ошибка: ожидаемое первичное выражение перед "for"|", "|38|ошибка: ISO C++ запрещает объявление `last' без типа |". Как это исправить?
 – 
Yasamura
4 Фев 2022 в 05:45
Это работает здесь: godbolt.org/z/3c3En1jf3 Какую командную строку вы используете?
 – 
Ben
4 Фев 2022 в 05:48
Я использую Code::Blocks с MinGW.
 – 
Yasamura
4 Фев 2022 в 05:55
Это c++17, поэтому используйте флаг компиляции: -std=c++17
 – 
Adriel Jr
4 Фев 2022 в 05:55
  1. Вставьте значения в каждом массиве во временный набор
  2. Для каждого значения в этом временном наборе, используя это значение в качестве ключа, увеличивайте значение элемента в окончательном наборе.
  3. Повторяйте 1-2, пока не закончите со всеми входными массивами.
  4. Общие элементы — это элемент в конечном наборе со значением, равным количеству массивов.

Или даже лучше:

  1. Вставьте значения в каждом массиве в input_set.
  2. Перейдите к следующему массиву и, если элемент находится в наборе input_set, сохраните его в наборе output_set.
  3. Пока есть следующий массив, поменять местами(input_set, output_set), очистить output_set и перейти к шагу 2.
  4. Повторяющиеся элементы находятся в выходном наборе.

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

1
Adriel Jr 4 Фев 2022 в 05:45
Это работает, но как сделать так, чтобы не было дублирования?
 – 
Yasamura
4 Фев 2022 в 05:56
Я не уверен, что ты имеешь в виду.
 – 
Adriel Jr
4 Фев 2022 в 05:58