当前位置: 首页 > 知识库问答 >
问题:

找到使2个字符串相等所需的最小移动

翁翰墨
2023-03-14

这是在线编码挑战之一(已完成)提出的问题<我只是需要一些逻辑来说明如何接近。


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

1. swap two consecutive characters of a string  
2. swap the first and the last characters of a string

移动可以在任一字符串上执行。
为了获得两个相等的字符串,我们需要的最小移动次数是多少?

输入格式和约束:
输入的第一行和第二行包含两个字符串A和B。保证它们的超集字符相等。

1 <= length(A) = length(B) <= 2000
All the input characters are between 'a' and 'z'


输出格式
将最小移动次数打印到输出的唯一行

Sample input:
aab
baa

Sample output:
1

说明:
交换字符串aab的第一个和最后一个字符以将其转换为baa。这两个字符串现在相等。

编辑:这是我的第一次尝试,但我得到了错误的输出。有人能指导我我的方法有什么问题吗?

int minStringMoves(char* a, char* b) {
    int length, pos, i, j, moves=0;
    char *ptr;
    length = strlen(a);

    for(i=0;i<length;i++) {
        // Find the first occurrence of b[i] in a
        ptr = strchr(a,b[i]);
        pos = ptr - a;

        // If its the last element, swap with the first
        if(i==0 && pos == length-1) {
            swap(&a[0], &a[length-1]);
            moves++;
        }
        // Else swap from current index till pos
        else {
            for(j=pos;j>i;j--) {
                swap(&a[j],&a[j-1]);
                moves++;
            }
        }

        // If equal, break
        if(strcmp(a,b) == 0)
            break;       
   }

   return moves;
}

共有3个答案

万俟宜修
2023-03-14

可以使用动态编程。在存储所有中间结果的同时,检查所有交换可能性,以及花费您最少的步骤。实际上,您将计算每个可能的目标字符串的最小步数,这些目标字符串可以通过应用给定的规则多次获得。一旦计算完所有步骤,就可以打印到达目标字符串所需的最小步数。以下是JavaScript中的示例代码,以及它在“aab”和“baa”示例中的用法:

function swap(str, i, j) {
   var s = str.split("");
   s[i] = str[j];
   s[j] = str[i];
   return s.join("");
}

function calcMinimumSteps(current, stepsCount)
{
   if (typeof(memory[current]) !== "undefined") {
      if (memory[current] > stepsCount) {
          memory[current] = stepsCount;
      } else if (memory[current] < stepsCount) {
          stepsCount = memory[current];
      }
   } else {
      memory[current] = stepsCount;
      calcMinimumSteps(swap(current, 0, current.length-1), stepsCount+1);
      for (var i = 0; i < current.length - 1; ++i) {
          calcMinimumSteps(swap(current, i, i + 1), stepsCount+1);
      }
   }
}

var memory = {};
calcMinimumSteps("aab", 0);
alert("Minimum steps count: " + memory["baa"]);
史劲
2023-03-14

A*算法可能适用于此问题。

初始节点将是原始字符串
目标节点将是目标字符串
节点的每个子节点都将是该字符串的所有可能转换
当前成本g(x)只是迄今为止的转换次数
启发式h(x)是错误位置字符数的一半。

由于h(x)是允许的(因为单个转换不能在其正确位置放置超过2个字符),因此目标字符串的路径将提供尽可能少的转换次数。

然而,初级实现可能会太慢。计算字符串的所有可能转换将是相当昂贵的。

请注意,节点的兄弟姐妹(父节点的子节点)与其子节点之间有很多相似之处。因此,您可以计算原始字符串的所有转换,并从那里简单地复制和重新计算涉及更改字符的数据。

彭星津
2023-03-14

看看这个例子:

aaaaaaaaab
abaaaaaaaa

您的解决方案:8

aaaaaaaaab -> aaaaaaaaba -> aaaaaaabaa -> aaaaaabaaa -> aaaaabaaaa -> 
aaaabaaaaa -> aaabaaaaaa -> aabaaaaaaa -> abaaaaaaaa

正确的解决方案:2

aaaaaaaaab -> baaaaaaaaa -> abaaaaaaaa

您应该检查在另一个方向上交换是否会提供更好的结果。

但有时你也会破坏字符串的前一部分。如:

caaaaaaaab
cbaaaaaaaa

caaaaaaaab -> baaaaaaaac -> abaaaaaaac

您需要在这里进行另一次交换,以将“c”放回第一位。

正确的算法可能更复杂,但现在您可以看到解决方案中的错误。

 类似资料:
  • 问题内容: 通过搜索发现了类似的问题,但我是一位新的(糟糕的)程序员,无法理解答案。 我有一个.txt文件,其中包含多个字符串,以’-‘分隔。我使用拆分将一些字符串分成变量,其中两个相等,但是在if语句中它们不相等。 这将产生以下结果: 瑞典 瑞典 没有 在两个“ Sweden”字符串之前和之后都有一个空格,并且它们都用大写字母“ S”编写,但不相等吗?我在哪里搞砸了? 问题答案: 最后一个元素包

  • 当且仅当“字符串中的所有不同字符重复相同次数”时,称字符串为良好字符串。 现在,给定一个长度为n的字符串,我们必须在这个字符串中进行的最小更改次数是多少,这样字符串就变得正常了。 注意:我们只允许使用小写英文字母,我们可以将任何字母更改为任何其他字母。 示例:让String为yyxzzxxx 那么这里的答案是2。 说明:一种可能的解决方案YYXYXX。我们已将2“z”更改为2“y”。现在“x”和“

  • 您将得到一个有N个节点的有根树。每个节点包含一个小写英文字母。标签为%1的节点是根。有Q个问题的形式,X,S:这里X是子树的根,S是一个字符串。 输入格式: 第一行输入由两个空格分隔的整数N和Q组成,它们分别是树中的节点数和问题数。下一行将包含N个空格分隔的小写英文字母,其中第i个字母将是存储在带有标签i的节点中的字母。接下来的n-1行中的每一行都包含两个空格分隔的整数u和v,表示在接下来的Q行后

  • 我正在学习最长公共子序列,使用以下算法: 公共级LCS{ 但是程序返回一个ErrorCharAt(未知来源),并且没有做任何事情。 另外,如果我将int i和j更改为0,那么下面的E将是索引-1和错误 我现在很迷路。有人能帮我吗?

  • 给出了一个大小为n的数组,其中表示位置处的硬币数量。“移动”包括将一定数量的硬币从位置移动到位置或。重新分配硬币所需的最小移动次数是多少,这样每个位置上正好有一枚硬币?你被保证有相同数量的硬币与有的插槽,以分配他们。 例如,给定输入 输出为 null 解决这个问题的有效方法是什么?

  • 问题内容: 这是我查询的结果,但顺序不正确。我想按最后2个字符排序。结果应为:下面。 我的查询: 第二:sqlfiddle 问题答案: 试试这个: 检查 SQL FIDDLE DEMO 输出