[动态规划]最长公共子序列

动态规划的本质

动态规划的实质就是:记忆化搜索。

对于要用动态规划进行解决的问题的特点:

  1. 问题具有最优子结构性质:如果问题的最优解包含的子问题的解也是最优的,就称该问题具有最优子结构。
  2. 问题具有子问题重叠性质:再用递归进行自顶向下计算时,每次产生的子问题并不都是新的,可能会存在子问题重复计算,动态规划就可以对每个子问题只计算一次,将结果保存起来,以便高效利用。

再来看一个问题: 最长公共子序列 POJ1458

给出两个字符串,求出这样的一个最长的公共子序列的长度。

思路:MaxLen(i,j) 表示s1的左边i个字符形成的子串,与s2左边的j个字符形成的子串的最长公共子序列的长度。

MaxLen(i, j) 就是本题的“状态”,定义一数组。

题目就是要求MaxLen(strlen(str1),strlen(str2))

[动态规划]最长公共子序列_第1张图片

[动态规划]最长公共子序列_第2张图片

代码:

#include 
#include

char str1[1000];
char str2[1000];
int MaxStrLen[1000][1000];

int max(int a, int b) {
  if (a > b)
    return a;
  else
    return b;
}

int main() {
  while (cin >> str1 >> str2) {
    int strLen1 = strlen(str1);
    int strLen2 = strlen(str2);
    int tmp;
    int i, j;
    for (i = 0; i < strLen1; i++)
      MaxStrLen[i][0] = 0;
    for (j = 0; j < strLen2; j++)
      MaxStrLen[0][j] = 0;
    for (int i = 1; i <= strLen1; i++) {
      for (int j = 1; j <= strLen2; j++) {
        if (str1[i - 1] == str2[j - 1])
          MaxStrLen[i][j] = MaxStrLen[i - 1][j - 1] + 1;
        else {
          MaxStrLen[i][j] = max(MaxStrLen[i][j - 1], MaxStrLen[i - 1][j]);
        }
      }
    }
    cout << MaxStrLen[strLen1][strLen2] << endl;
  }
}

你可能感兴趣的:(算法与数据结构,业余ACM)