Я думаю, потому что с большими объемами данных и отсутствием дополнительных критериев очень трудно будет сделать что-то, что найдет лучший вариант. Рассматривали ли вы вопрос об использовании жадного алгоритма (постепенно создавайте свое решение таким образом, чтобы вы могли найти что-то близкое к идеальному)? Вот моя идея:
Сортируйте наборы связанных символов по размеру и начинайте с самого большого. Держите их всех вместе, потому что без каких-либо других критериев мы могли бы также сказать, что их близость является наиболее важной, поскольку она является самой большой группой. Рассмотрим каждый символ в этом первом наборе «конечной точки», конечной точкой является символ, который вы можете переставить и поместить в любой конец массива, не повреждая правило близости (все в первом наборе изначально является конечной точкой, поскольку их можно переставить в любом путь). Затем просмотрите список и, как только один набор будет иметь один или несколько общих символов с первым, подключите их соответствующим образом. Символы, которые вы подключили друг к другу, больше не считаются конечными точками, но все остальное остается. Даже если у большего набора есть только один общий символ, я собираюсь догадаться, что это лучше, чем у меньшего набора с большим количеством общих символов, потому что таким образом, по крайней мере, больший набор остается вместе, а не может быть разделен, если он был положить в массив позже, чем меньшие наборы.
Я бы продолжил в том же духе, обновляя список существующих конечных точек, чтобы вы могли продолжать делать совпадения по мере того, как проходили ваш сет. Я бы отслеживал, прекратил ли я делать совпадения, и в этом случае я просто пошел бы на вершину списка и просто нажал на следующий самый большой, несопоставленный набор (не имеет значения, если больше нет совпадений, которые будут сделал, так что иди с самой ценной / самой большой ассоциацией). Откажитесь от старых конечных точек, так как у них нет совпадений, и тогда все символы набора, который вы только что прикрепили, являются новыми конечными точками.
Это может не иметь достаточно хорошего времени выполнения, я не уверен. Но, надеюсь, это даст вам некоторые идеи.
Редактировать: Очевидно, как часть алгоритма, дублирование рва (тривиально).