当前位置: 首页 > news >正文

动态规划 -- 最长公共子序列

最长公共子序列的结构

设序列 X={x1,x2,…,x m} 和 Y={y1,y2,…,y n} 的最长公共子序列为 Z={z1,z2,…,z k},则有以下结论:

  1. 若 x m=y n,则 z k=x m=y n,且 Z k−1(即 Z 去掉最后一个元素 z k 后的子序列)是 X m−1(即 X 去掉最后一个元素 x m 后的子序列)和 Y n−1(即 Y 去掉最后一个元素 y n 后的子序列)的最长公共子序列。

  2. 若 x m\=y n 且 z k\=x m,则 Z 是 X m−1 和 Y 的最长公共子序列。

  3. 若 x m\=y n 且 z k\=y n,则 Z 是 X 和 Y n−1 的最长公共子序列。

动规方程

c[i] [j]记录序列X和Y的最长公共子序列长度

代码实现

求最长子序列长度
int LCSLength(const char* X, const char* Y, int i, int j) { if (i == 0 || j == 0) { return 0; } else if (X[i] == Y[j]) { return LCSLength(X, Y, i - 1, j - 1) + 1; } else { int t1 = LCSLength(X, Y, i - 1, j);// X int t2 = LCSLength(X, Y, i, j - 1); if (t1 > t2) { return t1; } else { return t2; } } } ​ int main() { const int xm = 7; const int yn = 6; char X[xm + 1] = { '#','A','B','C','B','D','A','B' }; char Y[yn + 1] = { '#','B','D','C','A','B','A' }; ​ int maxlen = LCSLength(X, Y, xm, yn); cout << "maxlen: " << maxlen << endl; ​ return 0; }
求最长子序列(并优化防止重复计算)
int main() { const int xm = 7; const int yn = 6; char X[xm + 1] = { '#','A','B','C','B','D','A','B' }; // 0 1 2 3 4 5 6 7 // X[xm] char Y[yn + 1] = { '#','B','D','C','A','B','A' }; ​ std::vector<std::vector<int> > c(xm + 1, std::vector<int>(yn + 1, 0)); std::vector<std::vector<int> > s(xm + 1, std::vector<int>(yn + 1, 0)); printf("c vec: \n"); Print2Vec(c); printf("s vec: \n"); Print2Vec(s); int maxlen = LCSLength(X, Y, xm, yn,c,s); cout << "maxlen: " << maxlen << endl; cout << "num: " << num << endl; printf("c vec: \n"); Print2Vec(c); printf("s vec: \n"); Print2Vec(s); printf("data: \n"); LCS(X, xm, yn, s); return 0; }
不用递归实现
void Print2Vec(const std::vector<std::vector<int> >& c) { int yn = c[0].size(); int xm = c.size(); printf(" "); for (int i = 0; i < yn; ++i) { printf("%5d", i); } printf("\n"); for (int i = 0; i < xm; ++i) { printf("%3d ", i); for (int j = 0; j < yn; ++j) { printf("%5d", c[i][j]); } printf("\n"); } printf("\n---------------------------\n"); } int NiceLCSLength(const char* X, const char* Y, int xm, int yn, std::vector<std::vector<int> >& c, std::vector<std::vector<int> >& s) { for (int i = 1; i <= xm; ++i) // X { for (int j = 1; j <= yn; ++j) { if (X[i] == Y[j]) { c[i][j] = c[i - 1][j - 1] + 1; s[i][j] = 1; } else { if (c[i - 1][j] > c[i][j - 1]) { c[i][j] = c[i - 1][j]; s[i][j] = 2; } else { c[i][j] = c[i][j - 1]; s[i][j] = 3; } } } Print2Vec(c); } return c[xm][yn]; }
http://www.cnnetsun.cn/news/1583810.html

相关文章:

  • 别再乱点Quartus了!FPGA引脚分配的5个关键属性(Reserved/Group/Bank/Vref/I/O Standard)保姆级解读
  • 5分钟快速上手:AsrTools语音转文字工具完整指南
  • 让音乐歌词动起来:ESLyric高级歌词源完全指南
  • 医药行业全终端销售分析:从院内到院外,构建全景监控体系
  • 基于Fish-Speech-1.5的智能客服语音合成实战
  • Phi-3-Mini-128K开源大模型部署:高校实验室低成本AI教学平台建设
  • 索尼相机隐藏功能完全解锁指南:3个步骤释放专业级拍摄潜能
  • 保姆级教程:用CST Studio Suite 2024从零搭建一个2.4GHz WiFi贴片天线(含同轴馈电完整建模)
  • APP自动识别跳转各大应用商店(鸿蒙+iOS+安卓全品牌)|可直接部署落地页源码
  • Excel插件异常消失的深层解析与注册表修复方案
  • 高插拔寿命RJ45供应商盘点:国内哪些厂家机械寿命超过1000次?
  • 视频背景的懒加载技术
  • JPEGsnoop:图像深度解析技术的5大突破
  • 别再死记硬背了!用CLIP和对比学习,教你让AI模型看懂没见过的植物病害
  • Java——Java面向对象
  • Tomcat 启动内存的设置
  • YOLOv11n模型用Ultralytics官方工具转ncnn后,C++推理代码怎么改?
  • 宝塔面板Apache反向代理配置WSS服务:从握手失败到稳定连接的实战解析
  • JetCache异步API终极指南:如何快速提升Java系统响应性能
  • 掌握罗技鼠标宏:从入门到精通的绝地求生压枪系统配置指南
  • 避开这些坑,你的北理工计算机考研成功率能翻倍:过来人的血泪经验总结
  • BepInEx插件开发:从问题到实践的Unity扩展指南
  • OpenClaw+GLM-4.7-Flash:自动化PPT生成
  • FreeRTOS实战解析:portYIELD_FROM_ISR()在中断服务中的任务调度优化
  • 除了算命,这套测算系统源码还能怎么用?聊聊‘玄学+’的三种商业化思路
  • COMSOL磁可调太赫兹频段双带吸收器
  • 从CentOS到Rocky/Alma:手把手教你迁移服务器,告别‘停更焦虑’
  • 造相-Z-Image-Turbo 集成YOLOv8实战:智能人像构图与精修应用
  • 从按键消抖到报警器:用SR锁存器搞定两个经典硬件小项目(附Multisim仿真)
  • 目标检测模型评估:从AP到mAP@0.5:0.95的完整指南(附代码示例)