算法 – 计算将一个排列转换为另一个排列所需的相邻交换

We’re given two sequences of lowercase latin alphabet letters.
They’re both the same length and have the same amount of given types
of letters (the first has an equal number of t’s as the second and so
on). We are required to find the minimum number of swaps (by “swap” we mean changing
the order of two neighboring
letters) required to
transform the first sequence into the second. We
can safely assume every two sequences CAN be transformed
into each other. We could do this with brute-force, but the sequences are too long for that.

Input:
The length of the sequences (at least 2, at most 999999) and
then two sequences.

Output:
An integer representing the number of swaps needed for the
sequences to become the same.

Example:
{5, aaaaa, aaaaa} should output {0},
{4, abcd, acdb} should output {2}.

我想到的第一件事是bubblesort。我们可以简单计算每次交换的序列。问题是:a)它是O(n ^ 2)最坏情况b)我不相信它会给我最小的数字为每个case …即使优化的bubbleort似乎没有做的伎俩。我们可以实施鸡尾酒排序,解决海龟的问题,但它会给我最好的性能吗?或者有更简单/更快的东西?

这个问题也可以表述为:当只允许操作的时候,我们如何确定两个字符串之间的编辑距离?

最佳答案
这里有一个简单而有效的解决方案:

令Q [s2 [i]] = s2中的位置字符s2 [i]。令P [i] =在第二个字符串中对应于s1 [i]的字符的什么位置。

构建Q和P:

for ( int i = 0; i < s1.size(); ++i )
    Q[ s2[i] ].push_back(i); // basically, Q is a vector [0 .. 25] of lists

temp[0 .. 25] = {0}
for ( int i = 0; i < s1.size(); ++i )
    P[i + 1] = 1 + Q[ s1[i] ][ temp[ s1[i] ]++ ];

例:

    1234
s1: abcd
s2: acdb
Q: Q[a = 0] = {0}, Q[b = 1] = {3}, Q[c = 2] = {1}, Q[d = 3] = {2}
P: P[1] = 1, P[2] = 4 (because the b in s1 is on position 4 in s2), P[3] = 2
   P[4] = 3

P有2次反转(4 2和4 3),所以这是答案。

这个解决方案是O(n log n),因为构建P和Q可以在O(n)中完成,并且合并排序可以计数O(n log n)中的反转。

转载注明原文:算法 – 计算将一个排列转换为另一个排列所需的相邻交换 - 代码日志