sincerit LCS最长公共子序列

本文深入探讨了最长公共子序列(LCS)算法的实现细节,通过动态规划方法解决两个字符串的LCS问题,提供了完整的C++代码示例,包括状态转移方程、初始化条件、结果展示及回溯获取子序列的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <stdio.h>
#include <cstring>
#include <iostream>
#include <algorithm>
#define max(a,b)a>b?a:b 
using namespace std;
int dp[100][100]; // dp[i][j]表示第一个字符串以i结尾第二个字符串以j结尾的最长公共子序列 
// 转移方程 
// 如果str1[i] == str2[j]时 dp[i][j] = dp[i-1][j-1] + 1;
// str1[i] != str2[j]时  dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
// 初始条件是 dp[0][0~len2] = dp[0~len1][0] = 0; 
int vis[100][100];
// 用来标记一下我们找到的子序列的答案 
// vis[i][j] 第一个字串以i为结尾第二个字串以j为结尾开始往前找答案 
int LCS(char* str1, char* str2) {
  int len1 = strlen(str1);
  int len2 = strlen(str2);
  // 初始化
  for (int i = 0; i <= len1; i++) dp[i][0] = 0;
  for (int j = 0; j <= len2; j++) dp[0][j] = 0;
  for (int i = 1; i <= len1; i++) {
    for (int j = 1; j <= len2; j++) {
      if (str1[i-1] == str2[j-1]) { // 因为边界不可能小于0 
        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; // 表示是从(i-1, j)->(i, j)的 找字符的时候倒推过去 (i,j)->(i-1,j)
        } else {
          dp[i][j] = dp[i][j-1];
          vis[i][j] = 3;
        } 
      } 
    }
  }
  return dp[len1][len2];
}

// 过程表 
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"); 
}

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]; 
  }
}

int main() {
  char p[] = {"asdfghj"};
  char s[] = {"asdlkdfgh"};
  int ans = LCS(p, s);
  printf("%d\n", ans);
  show(p, s);
  getResult(strlen(p), strlen(s), p);
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值