更改字符串以使它们相等

时间:2015-02-19 06:18:20

标签: string algorithm

参考问题HERE

  

我们有两个字符串A和B,它们具有相同的超级字符集。我们   需要更改这些字符串以获得两个相等的字符串。在每一步中   我们可以执行以下操作之一:

     

1-交换字符串的两个连续字符
  2-交换第一个和   字符串的最后一个字符

     

可以对任一字符串执行移动。最低数量是多少?   为了获得两个相等的字符串我们需要的移动?输入   格式和约束:输入的第一行和第二行   包含两个字符串A和B.它保证超集它们的   人物是平等的。 1< = length(A)= length(B)< = 2000全部   输入字符在'a'和'z'之间

看起来这必须使用动态编程来解决。但我无法想出方程式。有人建议他们回答 - 但看起来并不合适。

dp[i][j] = 
Min{ 
dp[i + 1][j - 1] + 1, if str1[i] = str2[j] && str1[j] = str2[i]
dp[i + 2][j] + 1, if str1[i] = str2[i + 1] && str1[i + 1] = str2[i]
dp[i][j - 2] + 1, if str1[j] = str2[j - 1] && str1[j - 1] = str2[j]
}
In short, it's 
dp[i][j] = Min(dp[i + 1][j - 1], dp[i + 2][j], dp[i][j - 2]) + 1.
Here dp[i][j] means the number of minimum swaps needs to swap str1[i, j] to str2[i, j]. Here str1[i, j] means the substring of str1 starting from pos i to pos j :)

Here is an example like the one in the quesition,
str1 = "aab",
str2 = "baa"

dp[1][1] = 0 since str1[1] == str2[1];
dp[0][2] = str1[0 + 1][2 - 1] + 1 since str1[0] = str2[2] && str1[2] = str2[0].

1 个答案:

答案 0 :(得分:1)

你有两个原子操作:

  1. 连续交换成本1

  2. 首先换取成本1

  3. 一个有趣的事实:

    1. 和2.如果字符串end将附加到字符串begin(circular string)
    2. ,则相同

      因此我们可以推导出更通用的操作

      1. 将成本= |从 - 移动到|的字符(跨越国界)
      2. 这个问题对我来说似乎不是二维的,或者我无法确定尺寸。把这个算法当作天真的方法:

        private static int transform(String from, String to) {
            int commonLength = to.length();
            List<Solution> worklist = new ArrayList<>();
            worklist.add(new Solution(0,from));
            while (!worklist.isEmpty()) {
                Solution item = worklist.remove(0);
                if (item.remainder.length() == 0) {
                    return item.cost;
                } else {
                    int toPosition = commonLength - item.remainder.length();
                    char expected = to.charAt(toPosition);
                    nextpos : for (int i = 0; i < item.remainder.length(); i++) {
                        if (item.remainder.charAt(i) == expected) {
                            Solution nextSolution = item.moveCharToBegin(i, commonLength);
                            for (Solution solution : worklist) {
                                if (solution.remainder.equals(nextSolution.remainder)) {
                                    solution.cost = Math.min(solution.cost, nextSolution.cost);
                                    continue nextpos;
                                }
                            }
                            worklist.add(nextSolution);
                        }
                    }
                }
            }
            return Integer.MAX_VALUE;
        }
        
        private static class Solution {
            public int cost;
            public String remainder;
        
            public Solution(int cost, String remainder) {
                this.cost = cost;
                this.remainder = remainder;
            }
        
            public Solution moveCharToBegin(int i, int length) {
                int costOffset = Math.min(i, length - i); //minimum of forward and backward circular move
                String newRemainder = remainder.substring(0, i) + remainder.substring(i + 1);
                return new Solution(cost + costOffset, newRemainder);
            }
        }