sincerit LCS最长公共子序列

#include <stdio.h>
#include <cstring>
#define max(a,b)a>b?a:b
int dp[100][100]; // dp[i][j]表示str1到i结尾的子串与str2到j结尾的最大公共子串
// 转移方程 对于str1[i] == str2[j]时, dp[i][j] = dp[i-1][j-1] + 1
// 不同时 dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
// 初始值 dp[0][0~m] = dp[0~n][0] = 0; 也就是第0行和第0列都为0 
int vis[100][100];

int LCS(char* str1, char* str2) {
  memset(dp, 0, sizeof(dp));
  int str1_len = strlen(str1);
  int str2_len = strlen(str2);
  for (int i = 1; i <= str1_len; i++) {
    for (int j = 1; j <= str2_len; j++) {
      if (str1[i-1] == str2[j-1]) {
        dp[i][j] = dp[i-1][j-1] + 1;
        vis[i][j] = 1;
      } else {
        // dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
        if (dp[i-1][j] > dp[i][j-1]) {
          dp[i][j] = dp[i-1][j];
          vis[i][j] = 2;
        } else {
          dp[i][j] = dp[i][j-1];
          vis[i][j] = 3;
        }
      } 
    }
  }
  return dp[str1_len][str2_len];
}

void getResult(int i, int j, char* r) {
  if (i == 0 || j == 0) return;
  if (vis[i][j] == 1) {
    getResult(i-1, j-1, r); // 该位置找到了一个字符答案,因为dp[i][j] = dp[i-1][j-1]+1;
    printf("%c", r[i-1]); 
  } else if (vis[i][j] == 2) {
    getResult(i-1, j, r); // dp[i][j] = dp[i-1][j]; 
  } else {
    getResult(i, j-1, r);  // dp[i][j] = dp[i][j-1]; 
  }
}

void show(char* r, char* s) {
  printf("    ");
  for (int i = 0; i < strlen(s); i++) printf("%c ", s[i]);
  printf("\n");
  int k = 0;
  for (int i = 0; i <= strlen(r); i++) {
    if (i >= 1) printf("%c ", r[k++]);
    else printf("  ");
    for (int j = 0; j <= strlen(s); j++){
      printf("%d ", dp[i][j]);
    }
    printf("\n");
  }
  printf("\n"); 
}

int main() {
  char r[] = {"asdfghjkl"};
  char s[] = {"dfgcvzasdf"};
  printf("%s\n", r);
  printf("%s\n", s);
  int len = LCS(r, s);
  printf("%d\n", len);
  //show(r, s);  这里是个规律表
  getResult(strlen(r), strlen(s), r);
  return 0;
}

猜你喜欢

转载自blog.csdn.net/sincerit/article/details/84555923
今日推荐