**

解析:

**
此题一共有两个要点:
1.求上述两个最长公共子序列的长度
2.求所有可能出现的最长公共子序列个数,答案可能很大,只要将答案对10^8求余即可

第一个都很好想到,难点在于第二个。下面是对于求最长公共子序列的长度的一个动态规划图:

由此图可以看出,上述两个字符串的最大公共子序列的长度为4

重点:

此图的状态转移方程:
1.当s1[i]=s2[j]时:dp(i,j)=dp(i-1,j-1)+1
2.当s1[i]!=s2[j]并且dp(i-1,j)>=dp(i,j-1)时:dp(i,j)=dp(i-1,j)
3.否则:dp(i,j)=dp(i,j-1)

下面代码==>利用二维数组是求最大公共子序列的长度:

#include <iostream>
#include <string>
#include <vector>
using namespace std;
void lec(string s1,string s2){int m=s1.size();int n=s2.size();vector<vector<int>> dp(m+1);for(int i=0;i<=m;i++){dp[i].resize(n+1);}//转移状态方程for(int i=0;i<dp.size()-1;i++){for(int j=0;j<dp[i].size()-1;j++){if(s1[i]==s2[j]){dp[i+1][j+1]=dp[i][j]+1;}else{dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);}}}for(int i=0;i<dp.size();i++){for(int j=0;j<dp[i].size();j++){cout<<dp[i][j]<<" ";}cout<<endl;}cout<<"最长公共子序列为:"<<dp[m][n]<<endl;
}
int main(){string s1,s2;cin>>s1>>s2;lec(s1,s2);return 0;
}

下面代码==>利用两个一维数组是求最大公共子序列的长度:
大家可以试着利用此方法将状态转移图打印出来,下面代码只输出了最后的结果

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
void lec(string s1,string s2){int m=s1.size();int n=s2.size();vector<int> isDp(n+1);for(int i=0;i<m;i++){vector<int> nextDp(n+1);for(int j=0;j<m;j++){if(s1[i]==s2[j]){nextDp[j+1]=isDp[j]+1;}else{nextDp[j+1]=max(nextDp[j],isDp[j+1]);}}isDp=move(nextDp);}cout<<"最长公共子序列为:"<<isDp[n]<<endl;
}
int main(){string s1,s2;cin>>s1>>s2;lec(s1,s2);return 0;
}

重点来了——重点来了——重点来了

这也是此题的难点:
求出所有可能出现的最长公共子序列个数
创建一个二维数组 counts
状态转移方程
1.当s1[i]=s2[j]时:counts(i,j)=count(i-1,j-1)
2.当s1[i]!=s2[j]&&dp(i,j)=dp(i-1,j-1)时:counts(i,j)-=counts(i-1,j-1)
3.当dp(i,j)=dp(i-1,j)时:counts(i,j)+=counts(i-1,j)
4.当dp(i,j)=dp(i,j-1)时:counts(i,j)+=counts(i,j-1)

自述
说实话,这部分我现在也没搞太明白,若有大佬有幸看到这篇博客,希望可以留言指点一下,下面我将附上一篇讲解截图,并附上大佬博客链接:
蓝桥杯每日一题-最长公共子序列

下面附上代码:

下面使用两个二维数组实现的

#include <iostream>
#include <string>
#include <vector>
using namespace std;
const int MOD=(int)1e8;
void addMod(int& a,int b){a=(a+b)%MOD;
}
void lec(string s1,string s2){int m=s1.size();int n=s2.size();vector<vector<int>> dp(m+1);for(int i=0;i<=m;i++){dp[i].resize(n+1);}vector<vector<int>> counts(m+1);for(int i=0;i<=m;i++){counts[i].resize(n+1,1);}for(int i=0;i<dp.size()-1;i++){for(int j=0;j<dp[i].size()-1;j++){if(s1[i]==s2[j]){dp[i+1][j+1]=dp[i][j]+1;counts[i+1][j+1]=counts[i][j];}else{dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);counts[i+1][j+1]=0;if(dp[i+1][j+1]==dp[i][j]){addMod(counts[i+1][j+1],-counts[i][j]);}}if(dp[i+1][j+1]==dp[i+1][j]){addMod(counts[i+1][j+1],counts[i+1][j]);}if(dp[i+1][j+1]==dp[i][j+1]){addMod(counts[i+1][j+1],counts[i][j+1]);}}}for(int i=0;i<dp.size();i++){for(int j=0;j<dp[i].size();j++){cout<<dp[i][j]<<" ";}cout<<endl;}cout<<"最长公共子序列为:"<<dp[m][n]<<endl;for(int i=0;i<counts.size();i++){for(int j=0;j<counts[i].size();j++){cout<<counts[i][j]<<" ";}cout<<endl;}cout<<"最长公共子序列为:"<<counts[m][n]<<endl;
}
int main(){string s1,s2;cin>>s1>>s2;lec(s1,s2);return 0;
}

运行结果截屏

下面附上本题的AC代码
也就是用四个一维数组实现,实现了空间优化

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
const int MOD=(int)1e8;
void addMod(int& a,int b){a=(a+b)%MOD;
}
void lec(string s1,string s2){int m=s1.size();int n=s2.size();vector<int> isDp(n+1);vector<int> isCounts(n+1,1);for(int i=0;i<m;i++){vector<int> nextDp(n+1);vector<int> nextCounts(n+1,1);for(int j=0;j<m;j++){if(s1[i]==s2[j]){nextDp[j+1]=isDp[j]+1;nextCounts[j+1]=isCounts[j];}else{nextDp[j+1]=max(nextDp[j],isDp[j+1]);nextCounts[j+1]=0;if(nextDp[j+1]==isDp[j]){addMod(nextCounts[j+1],-isCounts[j]);}}if(nextDp[j+1]==isDp[j+1]){addMod(nextCounts[j+1],isCounts[j+1]);}if(nextDp[j+1]==nextDp[j]){addMod(nextCounts[j+1],nextCounts[j]);}}isDp=move(nextDp);isCounts=move(nextCounts);}cout<<"最长公共子序列为:"<<isDp[n]<<endl;cout<<"可能出现的最长公共子序列个数:"<<(isCounts[n]+MOD)%MOD<<endl;
}
int main(){string s1,s2;cin>>s1>>s2;lec(s1,s2);return 0;
}

本章到此就结束了,谢谢看客们光临本博客

经典算法题——最长公共子序列相关推荐

  1. leetcode算法题--最长公共子序列★

    原题链接:https://leetcode-cn.com/problems/longest-common-subsequence/ 动态规划 dp[i][j]表示text1[:i]和text2[:j] ...

  2. LCS算法:最长公共子序列

    LCS算法:最长公共子序列定义: 一个序列A任意删除若干个字符得到新序列B,则A叫做B的子序列 两个序列X和Y的公共子序列中,长度最长的那个,定义为X和Y的最长公共子序列 例如: X={A,B,C,B ...

  3. 用动态规划算法实现最长公共子序列问题的算法(java实现)

    用动态规划算法实现最长公共子序列问题的算法 public class longestCommonSubsequence {//构造追踪数组rec,记录子问题来源private static Strin ...

  4. java lcs_Java算法之最长公共子序列问题(LCS)实例分析

    本文实例讲述了Java算法之最长公共子序列问题(LCS).分享给大家供大家参考,具体如下: 问题描述:一个给定序列的子序列是在该序列中删去若干元素后得到的序列.确切地说,若给定序列X= { x1, x ...

  5. 数据结构与算法专题——第三题 最长公共子序列

    一:作用 最长公共子序列的问题常用于解决字符串的相似度,是一个非常实用的算法,作为码农,此算法是我们的必备基本功. 二:概念 举个例子,cnblogs这个字符串中子序列有多少个呢?很显然有27个,比如 ...

  6. 动态规划算法解最长公共子序列LCS问题

    动态规划算法解LCS问题 作者 July 二零一零年十二月三十一日 本文参考:微软面试100题系列V0.1版第19.56题.算法导论.维基百科. 第一部分.什么是动态规划算法 ok,咱们先来了解下什么 ...

  7. 触类旁通,经典面试题最长公共子序列应该这么答

    作者 |  labuladong 来源 | labuladong(ID:labuladong) [导读]最长公共子序列(Longest Common Subsequence,简称 LCS)是一道非常经 ...

  8. 365天挑战LeetCode1000题——Day 014 每日一题 + 最长公共子序列

    文章目录 1. [我能赢吗](https://leetcode.cn/problems/can-i-win/) 1.1 记忆化搜索+DFS+位运算 2. [最长公共子序列](https://leetc ...

  9. 动态规划算法---求最长公共子序列

    最长公共子序列和最长公共子串区别        最长公共子串(Longest Common Substring)与最长公共子序列(Longest Common Subsequence)的区别: 子串要 ...

最新文章

  1. chmod修改文件夹权限
  2. python代码大全o-python文件编码及执行
  3. SVN和Git的比较
  4. [视频]怎样提升asp.net mvc 软件的性能 - 微软免费视频Improving ASP.NET MVC Application Performance...
  5. Windows静态库和动态库的调用方法汇总
  6. STL源码剖析 第二次温习 细节审核
  7. 最新阿里内推高级Java面试题
  8. 鸿蒙HI3516-HAP的编译-2021426
  9. pyecharts折线图坐标轴范围设置_多层折线图,一对一展现数据趋势,图表就应如此美丽...
  10. 修改Python解释器和包路径
  11. 光纤接口类型及光纤收发器指示灯图解
  12. php laravel mix,Laravel框架 之 Mix
  13. h5页面定位偏移的问题--解答
  14. 使用AVFoundation完成照片拍摄存储相册, 开启关闭闪光灯, 切换摄像头
  15. 运营商-银联-手机厂商,三巨头如何依次主导NFC
  16. 叮咚,您有一份专线链路带宽管理方案,请查收
  17. 小程序的三种弹框showToast、showModal、showLoading
  18. Camera | 5.Linux v4l2架构(基于rk3568)
  19. 优秀网页翻译:DS3231与 PCF2129 RTC比较
  20. python学习——tsv文件批量转为csv文件、csv文件列合并

热门文章

  1. 8.排序——数据结构(严蔚敏C语言版)
  2. Spring Boot入门教程(二十五): Apache Shiro
  3. Lasso回归理论及代码实现
  4. python接入支付宝接口
  5. 高校bbs及科研论坛
  6. 数据价值深度挖掘,分析服务上线“探索”能力
  7. java中default关键字_Java 中的 default 关键字及代码示例
  8. FastDFS自定义文件存储系统
  9. ArrayList的add方法详解——让我们好好看看一个元素是如何插入到ArrayList集合当中(源码级别)
  10. 数据结构-头插法和尾插法