动态编程中的表如何工作?

时间:2013-09-20 04:45:54

标签: c++ string

我一直在研究动态编程,我在网站上遇到了代码。 问题是写一个函数,检查C是否是A和B的交错.C被称为交错A和B,如果它包含A和B的所有字符,则保留各个字符串中所有字符的顺序。我是什么不明白如何在二维矩阵中填充数值?

需要帮助:) 链接在这里 http://www.geeksforgeeks.org/check-whether-a-given-string-is-an-interleaving-of-two-other-given-strings-set-2/

// an interleaving of A and B, otherwise false.
bool isInterleaved(char* A, char* B, char* C)
{
  // Find lengths of the two strings
  int M = strlen(A), N = strlen(B);

  // Let us create a 2D table to store solutions of
  // subproblems.  C[i][j] will be true if C[0..i+j-1]
  // is an interleaving of A[0..i-1] and B[0..j-1].
  bool IL[M + 1][N + 1];

  memset(IL, 0, sizeof(IL)); // Initialize all values as false.

  // C can be an interleaving of A and B only of sum
  // of lengths of A & B is equal to length of C.
  if ((M + N) != strlen(C))
    return false;

  // Process all characters of A and B
  for (int i = 0; i <= M; ++i)
  {
    for (int j = 0; j <= N; ++j)
    {
      // two empty strings have an empty string
      // as interleaving
      if (i == 0 && j == 0)
        IL[i][j] = true;

      // A is empty
      else if (i == 0 && B[j - 1] == C[j - 1])
        IL[i][j] = IL[i][j - 1];

      // B is empty
      else if (j == 0 && A[i - 1] == C[i - 1])
        IL[i][j] = IL[i - 1][j];

      // Current character of C matches with current character of A,
      // but doesn't match with current character of B
      else if (A[i - 1] == C[i + j - 1] && B[j - 1] != C[i + j - 1])
        IL[i][j] = IL[i - 1][j];

      // Current character of C matches with current character of B,
      // but doesn't match with current character of A
      else if (A[i - 1] != C[i + j - 1] && B[j - 1] == C[i + j - 1])
        IL[i][j] = IL[i][j - 1];

      // Current character of C matches with that of both A and B
      else if (A[i - 1] == C[i + j - 1] && B[j - 1] == C[i + j - 1])
        IL[i][j] = (IL[i - 1][j] || IL[i][j - 1]);
    }
  }

  return IL[M][N];
}

void test(char *A, char *B, char *C)
{
  if (isInterleaved(A, B, C))
    cout << C << " is interleaved of " << A << " and " << B << endl;
  else
    cout << C << " is not interleaved of " << A << " and " << B << endl;
}

// Driver program to test above functions
int main()
{
  test("XXY", "XXZ", "XXZXXXY");
}

1 个答案:

答案 0 :(得分:2)

Dynamic programming重新使用子问题的结果来解决问题。子问题是问题的较小版本。表通常用于存储子问题结果。

表的索引是特定于应用程序的;在这种情况下,它们在评论中描述:

// Let us create a 2D table to store solutions of
// subproblems.  IL[i][j] will be true if C[0..i+j-1]
// is an interleaving of A[0..i-1] and B[0..j-1].

(我修正了一个错误,C[i][j]应该是原始来源中的IL[i][j]

子问题确定AB的子串是否是C的子串的交错.IL阵列中的索引确定A和{{的子串的长度。 1}}(第三个子串的长度隐含在另外两个的长度上)。

例如:

  • BIL[0][0],因为“”(空字符串)和“”交错形成“”。
  • true也是IL[0][*],因为“”和true交错形成WHATEVER(此处,WHATEVER表示“任何事情”)。
  • *也是IL[*][0],原因与上述类似。
  • true的计算方法是将IL[i][j]中的当前字符与CA中的当前字符进行比较(查看源代码以确定我的意思)当前”)
    • 如果两者都不匹配,则表示B 是交错,因为它包含意外字符。因此,C
    • 如果匹配IL[i][j] = false,那么您还需要检查前面的字符是否也正确交错。这里是动态编程部分的用武之地 - 您不需要实际查看所有这些字符来检查它们,因为您已经在之前的迭代中完成了这些操作。检查的结果(也是您应该返回的最终结果)存储在A表中,更具体地说,存储在IL中。因此,IL[i-1][j]
    • 如果匹配IL[i][j] = IL[i-1][j],则执行与上述相同的操作,但请查看B

如果您无法理解动态编程解决方案,我建议您手动完成站点上的递归解决方案。最终,你会发现你正在重复许多比较。您可以通过在第一次进行比较时存储比较结果来避免重复,然后在以后的场合重复使用该结果。