要区分子串和子序列的区别
NC127 最长公共子串
dp[i] [j]表示两个串分别以i和j结尾的最长公共子串。这个求子串可以直接截取。
class Solution {
public:
string LCS(string str1, string str2) {
// write code here
//if(str1==""||str2=="" ) return "";
str1=" "+str1;
str2=" "+str2;
int dp[str1.size()+5][str2.size()+5];
int Max=0;
string s="";
for(int i=0;i<str1.size();i++)
{
dp[i][0]=0;
}
for(int i=0;i<str2.size();i++)
{
dp[0][i]=0;
}
for(int i=1;i<str1.size();i++)
{
for(int j=1;j<str2.size();j++)
{
if(str1[i]==str2[j])
{
dp[i][j]=dp[i-1][j-1]+1;
}
else
{
// dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
dp[i][j]=0;
}
if(dp[i][j]>Max)
{
s=str1.substr(i-dp[i][j]+1,dp[i][j]);
Max=dp[i][j];
}
}
}
return s;
}
};
最长公共子序列
先使用动态规划计算出以i,j结尾的最大子序列,计算出来之后利用它从后想前遍历一边,找出最大子序列。
class Solution {
public:
string LCS(string s1, string s2) {
int dp[s1.size()+5][s2.size()+5];
for(int i=0;i<s1.size()+5;i++)
{
dp[i][0]=0;
}
for(int i=0;i<s2.size()+5;i++)
{
dp[0][i]=0;
}
if(s1.size()==0||s2.size()==0) return "-1";
// write code here
s1=" "+s1;
s2=" "+s2;
for(int i=1;i<s1.size();i++)
{
for(int j=1;j<s2.size();j++)
{
if(s1[i]==s2[j])
{
dp[i][j]=dp[i-1][j-1]+1;
}
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
//cout<<dp[s1.size()-1][s2.size()-1]<<endl;
if(dp[s1.size()-1][s2.size()-1]==0) {
return "-1";
}
string s="";
// int i=1,j=1;
// while(i<s1.size()&&j<s2.size())
// {
// if(s1[i]==s2[j])
// {
// s+=s1[i];
// i++;
// j++;
// }
// else
// {
// if(dp[i][j+1]>dp[i+1][j]) j++;
// else i++;
// }
// }
int i=s1.size()-1,j=s2.size()-1;
while(i>=1&&j>=1)
{
if(s1[i]==s2[j])
{
s+=s1[i];
i--;
j--;
}
// else if(i==s1.size()-1||j==s2.size()-1)
// {
// break;
// }
else
{
if(dp[i][j-1]>dp[i-1][j]) j--;
else i--;
}
}
reverse(s.begin(), s.end());
return s;
}
};