**

解析:

**
此题一共有两个要点:
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. http网址捆綁代理php_PHP获取IP,HTTP代理问题
  2. mybatis generator Unknown system variable 'query_cache_size' 的解决方法
  3. 如何用python 开发web_如何用python开发web
  4. 程序员绩效总结_年终总结怎么写?
  5. hive中导入text文件遇到的坑
  6. 【Elasticsearch】搜索类型 SearchType
  7. keras实例学习-双向LSTM进行imdb情感分类
  8. 随机森林分类算法python代码_随机森林的原理及Python代码实现
  9. JAVA中pin什么意思_银行业加密算法,PIN相关算法(java-国密)
  10. 深度学习caffe:权值初始化
  11. 数据是否服从正态分布
  12. java程序设计俄罗斯方块_Java俄罗斯方块实现代码
  13. 机器学习——数据的预处理(总结大全)
  14. 有没有不收费的恢复数据软件下载 分享人性化数据恢复工具
  15. 基于spring boot的人民医院体检预约系统
  16. 单条知识:什么是平面束方程
  17. 微信小程序图片显示模式
  18. python文本分类算法_基于Naive Bayes算法的文本分类
  19. java反射底层原理。
  20. mysql8实战_实战MySQL8.0.17 Clone Plugin

热门文章

  1. ibatis中配置parameterClass=java.util.HashMap的用法
  2. 【Android开发】apktool官网及最新版本
  3. 软件测试方法大全,49种测试方法,你知道几个?
  4. Unity开发HTC vive 五、拾取和触碰
  5. 如何使用 Python 检测和识别车牌(附 Python 代码)
  6. 商务智能-第六章 数据挖掘
  7. 数据结构课程设计(部分选题)
  8. 松鼠分松果解题 c++
  9. 【SQL 解决鸡兔同笼问题】
  10. 文件服务器+权限+迁移,文件服务器文件夹,共享文件夹及权限迁移