【问题标题】:Minimum edit distance of zig zag string之字形字符串的最小编辑距离
【发布时间】:2014-02-03 13:13:10
【问题描述】:

我有这样的字符串 xxoxxooo,我想将其编辑为这种形式 xoxoxoxo,我的问题是如何找到最小交换数,我只能交换 2 个邻居作为交换。我考虑过遍历字符串并找到最近的冗余 x 并将其移动到当前位置,但我认为这太慢了,因为字符串可以有 1e6 * 2 个字符。有什么想法吗?

【问题讨论】:

    标签: c++ algorithm edit-distance zigzag


    【解决方案1】:

    让我们表示s_i 位置ii+1 之间的交换

    假设您有一个从AB 的最小交换序列S = s_{i1} s_{i2} ...。因为它是最小的,所以您只能将xo 交换,而绝不将xxoo 交换。因此S 的操作是将A 的第一个o 发送到B 的第一个o,将A 的第二个o 发送到B 的第二个o 和很快。所以swap的数量不能小于

    Sum_i abs(pos of i-st o in A - pos of i-st o in B)
    

    现在很容易找到恰好具有这个交换次数的序列,因此这是正确的值。

    这是一个计算它的算法

    Input: s1 and s2 of common length n
    I'm assuming that they contains the same number of 'x' and 'o'
    
    res = 0;
    i1 = 0; i2 = 0;
    while true do
        // find the next o
        while i1 < n and s1[i1] == 'x' do
            i1++
        if i1 == n return res
        // no check that i2 < n because of assumption
        while s2[i2] == 'x' do 
            i2++
        res += abs(i1-i2)
        i1++; i2++
    

    【讨论】:

      【解决方案2】:

      您可以忽略其中一种字符类型,并计算其他类型字符中的每一种到每个目标位置的距离。

      更具体地说,所选类型字符的第 i 次出现将始终映射到第 i 个目标位置 - 将其移过该点是多余的(因为我们将交换两个相同的在某个时候输入),如果它没有移到那里,那么一侧的那种类型的字符就不够了。此外,由于我们只能交换相邻的字符,因此我们采取的移动次数正好等于将字符移到某个位置的距离。

      这可以通过以下算法完成:(伪代码)

      distance = 0
      pos = 0
      for i = 0 to n
        if i == 'x'                     // only check 'x's
          distance += abs(i - pos)      // calculate distance to target position
          pos += 2                      // move to the next position
      

      你的例子:

      index      0 1 2 3 4 5 6 7
      character  x x o x x o o o
      distance 0 0 1 1 2 4 4 4 4
      pos      0 2 4 4 6 8 8 8 8
      

      所以距离是4。

      【讨论】:

      • 我想出了这个pastebin.com/qbAUMU30,结果是 min(minSwaps(array, size, 0), minSwaps(array2, size, 1)) 可以吗?
      • 如果您的代码不起作用,请再问一个问题,或者在codereview.stackexchange.com 上进行审核。话虽如此,链接的代码远非最佳,它具有 O(n^2) 复杂度,而您可以通过使用类似于合并的技巧来获得 O(n)。请参阅我的帖子中即将进行的编辑。
      • @user1295618 如果你试图遵循我的伪代码(或者即使你不是),那你就过于复杂了——你真的只需要一个 for 循环(pos应在循环外部声明并在 if 语句内递增,如在伪代码中)。
      • 我遵循了 hivert 的想法,但这是我对你想法的实现,但它不起作用,pastebin.com/eXbcuZ5Q。它又给出了一个错误的结果。输入是这种形式 1 1 1 1 0 0 0 0 , 1 = x, 0 = o
      最近更新 更多