您的位置:首页 > 其它

最长公共子序列

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: