Вы не знаете, насколько грубым является ваш подход. Пока вы используете функции набора запросов в пространстве имен std ::, они могут быть настолько эффективными, насколько это возможно.
Например, тестирование, если set_intersection (s1.begin (), s2.end (), m1.begin (), m1.end ()) эквивалентно m1.
Вы могли бы быть более эффективным, чем это, поскольку вам не нужна копия соответствующих элементов, просто чтобы знать, что все они появляются. Это можно сделать, скопировав код set_intersection, но изменив реализацию так, чтобы просто считать количество подходящих элементов, а не копировать их. Тогда, если количество совпадает с размером m, то у вас есть совпадение.
Что касается контейнеров, я часто предпочитаю сортированную деку над набором для больших коллекций. Память гораздо меньше распределяется по куче, что помогает с кэшированием. Это также позволяет избежать накладных расходов нижележащего дерева. Это особенно полезно, когда контейнеры создаются один раз, но поиск выполняется несколько раз.