问题描述:
输入两个字符串,输出最长子序列长度和子序列字符串!
解决思想:
1.动态规划:状态数组 dp[i][j] 表示存储长度 i、j 的公共子序列长度
2.状态转移方程1:dp[i][j]=dp[i-1][j-1]+1;(最后一个元素相等)
状态转移方程2:dp[i][j]=max(dp[i-1][j],dp[i][j-1]);(最后一个元素不相等)
具体动态规划思想解决问题可参考我的另一篇博客: 贪心算法与动态规划_(解题步骤、区别联系)
样例输入:
输入两行,每行为一个字符串!
abcdefg
ababcd
样例输出:
输出两行,第一行为长度,第二行为最长公共子序列!
4
abcd
AC代码:
#include<bits/stdc++.h>
using namespace std;
string str1;
string str2;
//存储字符串长度
int m;
int n;
//状态数组
int dp[100][100]; //存储长度 i、j 的公共子序列长度
void getResult(){
m=str1.length();
n=str2.length();
int i,j;
for(i=0;i<=m;i++){
for(j=0;j<=n;j++){
//初始化
if(i==0||j==0){
dp[i][j]=0;
}
else if(str1[i]==str2[j]){ //当最后一个元素相等
dp[i][j]=dp[i-1][j-1]+1; //状态转移方程 1
}
else{ //最后一个元素不等
dp[i][j]=max(dp[i-1][j],dp[i][j-1]); //状态转移方程 2
}
}
}
cout<<dp[m][n]<<endl;
//输出相同字符串序列
int k=dp[m][n]; //最长公共子序列
int len=k; //存储k值,便于后续输出
string ch[k+1];
i=m,j=n;
while(k>=0){
if(dp[i][j]==dp[i][j-1]){
j--;
}
else if(dp[i][j]==dp[i-1][j]){
i--;
}
else{
ch[k]=str1[i];
i--,j--,k--;
}
}
//输出
for(i=0;i<=len;i++){
cout<<ch[i];
}
}
int main(){
getline(cin,str1);
getline(cin,str2);
//初始化状态数组
memset(dp,0,sizeof(dp));
getResult();
return 0;
}