Поиск минимального количества свопов для преобразования одной строки в другую, где строки могут иметь повторяющиеся символы

Я просматривал вопрос программирования, когда следующий вопрос внезапно казался связанным.

Как преобразовать строку в другую строку, используя несколько свопов, как показано ниже. Строки гарантированно взаимно обратимы (они имеют одинаковый набор символов, это задано), , но символы могут быть повторены. Я видел веб-результаты по одному и тому же вопросу, без повторения символов. Любые два символа в строке могут быть заменены.

Например: "aabbccdd" можно преобразовать в "ddbbccaa" двумя свопами, а "abcc" можно преобразовать в "accb" за один обмен.

Спасибо!

Ответы

Ответ 1

Это расширенная и исправленная версия ответа Subhasis.

Формально проблема заключается в том, что для n-буквенного алфавита V и двух m-буквенных слов x и y, для которых существует такая перестановка p, что p (x) = y, определяет наименьшее число свопов ( перестановки, фиксирующие все, кроме двух элементов), состав которых q удовлетворяет q (x) = y. Предполагая, что n-буквенные слова являются отображениями из множества {1,..., m} в V и что p и q являются перестановками на {1,..., m}, действие p (x) определяется как состав p, за которым следует x.

Наименьшее количество свопов, состав которых равен р, может быть выражен через циклическое разложение р. Когда j 1,..., j k попарно различаются в {1,..., m}, цикл (j 1... j k) является перестановкой, которая отображает j i на j я + 1 для я в {1,..., k - 1}, отображает j k на j 1 и отображает каждый другой элемент в себя. Перестановка p представляет собой композицию каждого отдельного цикла (j p (j) p (p (j))... j '), где j произвольно и p (j') = j. Порядок композиции не имеет значения, так как каждый элемент появляется точно в одном из составленных циклов. Цикл k-элементов (j 1... j k) можно записать как произведение (j 1 j k) (j 1 j k - 1)... (j 1 j 2)) k - 1 цикл. В общем, каждая перестановка может быть записана как композиция m свопов за вычетом количества циклов, включающих его разложение цикла. Прямое индукционное доказательство показывает, что это оптимально.

Теперь мы доходим до сути ответа Subhasis. Экземпляры проблемы с азбукой соответствуют друг другу с эйлеровым (для каждой вершины, в градусах, равна -дегре) орграфов G с вершинами V и m дугами с меткой 1,..., m. Для j в {1,..., n} дуга, помеченная j, переходит от y (j) в x (j). Задача с точки зрения G состоит в том, чтобы определить, сколько частей может иметь разбиение дуг G на направленные циклы. (Так как G эйлерова, такое разбиение всегда существует.) Это связано с тем, что перестановки q такие, что q (x) = y находятся во взаимно однозначном соответствии с разбиениями следующим образом. Для каждого цикла (j 1... j k) q существует часть, направленный цикл которой состоит из дуг, помеченных j 1,..., j k.

Проблема с уменьшением жесткости NP-субхазиса заключается в том, что наложение на дилатацию на эйлеровом орграфе на дуговой развязке является частным случаем упаковки дугообразных циклов на общих орграфах, поэтому результат NP-твердости для последнее не имеет прямых последствий для статуса сложности первого. В очень недавняя работа (см. Цитату ниже), однако было показано, что действительно даже особый случай Эйлера - NP-hard, Таким образом, в соответствии с вышеизложенным, проблема с аськой также.

В качестве подсказок субасида эта проблема может быть решена в полиномиальное время, когда n, размер алфавита, фиксирован (фиксированный параметр обрабатывается). Поскольку существует O (n!) Различимых циклов, когда дуги немаркированы, мы можем использовать динамическое программирование на пространстве состояний с размером O (m n), числом различимых подграфов. На практике это может быть достаточным для (пусть говорят) двоичного алфавита, но если бы я попытался решить эту проблему именно на экземплярах с большими алфавитами, то я, скорее всего, попробовал бы разветвление и привязку, получив оценки с помощью линейного программирования с генерацией столбцов для пакетных циклов.

@article{DBLP:journals/corr/GutinJSW14,
  author    = {Gregory Gutin and
               Mark Jones and
               Bin Sheng and
               Magnus Wahlstr{\"o}m},
  title     = {Parameterized Directed \$k\$-Chinese Postman Problem and \$k\$
               Arc-Disjoint Cycles Problem on Euler Digraphs},
  journal   = {CoRR},
  volume    = {abs/1402.2137},
  year      = {2014},
  ee        = {http://arxiv.org/abs/1402.2137},
  bibsource = {DBLP, http://dblp.uni-trier.de}
}

Ответ 2

Вы можете построить строки "разности" S и S', то есть строку, которая содержит символы в разных положениях двух строк, например. для acbacb и abcabc это будет cbcb и bcbc. Скажем, это содержит n символов.

Теперь вы можете построить "граф перестановок" G, который будет иметь n узлы и ребро от i до j, если S[i] == S'[j]. В случае всех уникальных символов легко видеть, что требуемое количество свопов будет (n - количество циклов в G), которое можно обнаружить в O (n) времени.

Однако в случае, когда имеется любое количество повторяющихся символов, это сводится к задаче нахождения наибольшего числа циклов в ориентированном графе, который, я думаю, является NP-hard (например, проверьте: http://www.math.ucsd.edu/~jverstra/dcig.pdf).

В этой статье указывается несколько жадных алгоритмов, одна из которых особенно проста:

Однако могут быть эффективные алгоритмы, использующие свойства вашего случая (единственное, о чем я могу думать, это то, что ваши графики будут K-partite, где K - количество уникальных символов в S). Удачи!

Изменить: Пожалуйста, обратитесь к Дэвиду за более полное и правильное объяснение проблемы.

Ответ 3

Сделайте поиск A * (см. http://en.wikipedia.org/wiki/A-star_search_algorithm для объяснения) для кратчайшего пути через график эквивалентных строк из одной строки в другой. Используйте расстояние Левенштейна /2 в качестве эвристической стоимости.

Ответ 4

Первое, на что нужно ответить, -

What is a mismatch ?

Несоответствие - это когда символы не соответствуют порядку.

When are characters out of order ?

Первое предположение: две строки являются взаимозаменяемыми.

Второе предположение: обе строки имеют одинаковую длину.

Таким образом, из-за порядка означает, что для символа i в первой строке конечно существует другой символ в позиции j во втором строка.

When are swaps required ?

Итак, для любого заданного индекса i, если символы в обеих строках не равны. Существует несоответствие. Сколько несоответствий? 2 несоответствия. Поскольку несогласованный символ из первой строки вызовет несоответствие во второй строке в другой позиции j. Таким образом, общее количество несоответствий всегда будет кратным 2.

Один своп корректирует положение в 2 символа. Таким образом, оптимальное количество несоответствий составляет половину общего числа несоответствий.

Вот пример кода.

public class CharacterMismatch {
    /**
     * Returns -1 if not possible
     * @param first
     * @param second
     * @return
     */
    public static int maxSwaps(char first[], char second[]) {
        if (first.length != second.length) {
            return -1;
        }
        int freqFirst[] = new int[Character.MAX_VALUE], freqSecond[] = new int[Character.MAX_VALUE];
        int len = first.length;
        for (int i = 0; i < len; ++i) {
            freqFirst[first[i]]++;
            freqSecond[second[i]]++;
        }

        for (int i = 0; i < len; ++i) {
            if (freqFirst[i] != freqSecond[i]) {
                return -1;
            }
        }

        //count mismatches. That is the minimal number of swaps required.
        int swaps = 0;
        for (int i = 0; i < len; ++i) {
            if (first[i] != second[i]) {
                swaps++;
            }
        }

        return swaps / 2;
    }

    public static void main(String[] args) {
        String first[] = { "aabbccdd", "abcc", "abccab" };
        String second[] = { "ddbbccaa", "accb", "abcabc"};

        for (int i = 0; i < first.length; ++i) {
            System.out.printf("%s %s => %d%n", first[i], second[i], maxSwaps(first[i].toCharArray(), second[i].toCharArray()));
        }
    }
}

Возвращает

aabbccdd ddbbccaa => 2
abcc accb => 1
abccab abcabc => 1

Сложность - это O (n).

Существует некоторый код плиты котла, который проверяет, действительно ли они взаимозаменяемы, проверяя частоту каждого символа в обеих строках и возвращает -1, если это невозможно.

Edit:

Извините, это работает только тогда, когда максимальное количество свопов для каждого несоответствующего символа не более одного.

Ответ 5

Структура данных хэш-карты (которая позволяет дубликаты) подходит для решения проблемы.

Пусть строка будет s1 и s2. Алгоритм выполняет итерацию по строке и всякий раз, когда обнаружено несоответствие, алгоритм отображает символ s1 в s2, т.е. char s1 в качестве ключа и char для s2, поскольку значение вставляется в Hash Map везде, где происходит несоответствие.

После этого инициализируйте результат как ноль.

Следующим шагом является то, что Hash Map не пуст, выполните следующие действия:

  • Для любого ключа k найдите его значение v.
  • Теперь используйте значение v в качестве ключа для поиска в Hash-карте, чтобы найти значение, если найденное значение равно k, а затем увеличивайте результат на 1 и удалите обе клавиши k и v из Hash-карты.
  • Если найденное значение не равно k, то удалите ключ k из Hash-карты и увеличивайте результат.
Результат

содержит желаемый результат.