最长公共子序列
2017-11-14 12:27
183 查看
题目描述
给你俩个字符串,找公共最长的子序列串。分析
根据第一个串的长度M,第二个串的长度N,建立一个MXN的二维表。这个表 dp [i][j] ,代表 第一个串从 0 ~ i号下标和第二个串从0~j号下标这俩个字串的最长公共子序列。
那么这个表的初始状态是,dp[0][0]~dp[M-1][0]的值为,如果第一个串的 i 号元素跟第二个串的0号元素相等则值为1否则值为0,但是如果dp[i-1][0]的值为1,那么dp[i][0]的值也为1。因为i-1 是 i的字串,所以 i-1 有的公共字符在i中也一定有。对于dp[0][0]~dp[0][N-1]这个初始化跟上面这个类似。
那么dp[i][j]的公式是这样的,如果dp[i][j]可能有三种情况而来:
1.dp[i-1][j]来
2.dp[i][j-1]来
3.dp[i-1][j-1]来
那么就很简单了,分析下,dp[i-1][j]、dp[i][j-1]、dp[i-1][j-1]它们三个都相差一个字符,其中dp[i-1][j-1]又是它们俩个的子序列。那么它们的三个值如果相差最多差值为1。就在于这三个序列,一个新增了一个s1串的字符,一个新增了s2串的一个字符,一个没有新增。
那么新增s1串的字符的子序列,可能因为新增后又有一个公共子序列字符,那么dp[i][j]应该选它。新增s2串的字符的子序列同理。
那么可能,前面俩个新增后都没有多公共子序列字符,那么可能是第i个字符与第j个字符相等导致多了一个公共子序列的字符,那么这个时候dp[i][j]的值,就应该等于没有新增字符的dp[i-1][j-1]的值加1了。
用代码的思路就是,先从dp[i-1][j]与dp[i][j-1]中选个最大的,然后如果s1[i]==s2[j]的话,看dp[i-1][j-1]+1的值是否大于刚更新过的dp[i][j],如果大于重新更新下就Ok。
代码
#include<iostream> #include<vector> #include<string> using namespace std; void Getdp(std::string&s1 ,std::string&s2,vector<vector<int>>&ret) { int m = s1.size(); int n = s2.size(); for(int i=0;i<m;++i) { ret[i][0]=((s1[i]==s2[0]||(i>0&&ret[i][0]==1)))?1:0; } for(int i=0;i<n;++i) { ret[0][i]=((s2[i]==s1[0]||(i>0&&ret[0][i]==1)))?1:0; } for(int i=1;i<m;++i) { for(int j=1;j<n;++j) { ret[i][j]=(ret[i-1][j]>ret[i][j-1])?ret[i-1][j]:ret[i][j-1]; if(s1[i]==s2[j]&&ret[i-1][j-1]+1>ret[i][j]) ret[i][j]=ret[i-1][j-1]+1; } } } std::string GetSub(std::string & s1 ,std::string & s2 ) { vector<vector<int>> dp(s1.size()); for(auto&i:dp) { i.resize(s2.size()); } Getdp(s1,s2,dp); int m =s1.size(); int n =s2.size(); std::string ret; ret.resize(dp[m-1][n-1]); int count = ret.size()-1; int Row = m-1; int Col = n-1; while(count>=0) { if(Row>0&&dp[Row-1][Col]==dp[Row][Col]) --Row; else if(Col>0&&dp[Row][Col-1]==dp[Row][Col]) --Col; else { ret[count--]=s1[Row]; --Row,--Col; } } return ret; } int main() { std::string s1 = "1A2C3D4B56"; std::string s2 = "B1D23CA45B6A"; std::string ret=GetSub(s1,s2); std::cout<<ret<<std::endl; return 0; }
相关文章推荐
- 最长公共子序列
- 最长公共子序列
- 【算法导论】动态规划之最长公共子序列
- (Relax DP1.6)UVA 10405 Longest Common Subsequence(使用DP来求解最长公共子序列LCS)
- 最长公共子序列
- 九度OJ 1042 Coincidence -- 动态规划(最长公共子序列)
- 最长公共子序列(LCS)问题
- HDU 1503 最长公共子序列的变形(重点在输出)
- Python实现各类数据结构和算法---动态规划之最长公共子序列
- 最长公共子序列(加强版) Hdu 1503 Advanced Fruits
- UVA 10405 LONGEST COMMON SUBSEQUENCE(最长公共子序列)
- 最长公共子序列--【算法导论】
- 2014省赛大总结(二) 最长公共子序列系列
- POJ 1458 Common Subsequence (动规,最长公共子序列)
- 最长公共子序列及Python实现
- 最长公共子序列
- UVA 531 Compromise 最长公共子序列(DP)
- xyoj 1132:最长公共子序列
- UVA Compromise(最长公共子序列 + 打印路径)
- 最长公共子序列(LCS)