问题描述:
给定两个序列s1,s2,求二者的最长公共子序列长度
例如:
algorithms
alchemist
输出:5
即alhms
1.设计状态:
f[i][j]表示的是s1有i个字母,s2有j个字母,他们的最长公共子序列
2.转移状态方程
f[i][j]=0,? i==0 || j==0;
f[i][j]=f[i-1][j-1]+1;? s1[i-1]==s1[j-1]
f[i][j]=max(f[i-1][j],f[i][j-1]) s1[i-1]!=s1[j-1]
最后要想输出子序列实际是什么,可以通过递归从后往前返回,然后把输出放在递归之后,这样回溯的时候就会顺序输出,这里如果i==0||j==0就是到达边界了,直接返回;否则如果元素相等说明f[i][j]是通过f[i-1][j-1]得到的,并且在这里输出,如果不相等并且f[i-1][j]>f[i][j-1] 说明从f[i-1][j]得到的
?
?
#include<iostream>
#include<cstring>
using namespace std;
int f[1010][1010];
string s1;
string s2;
void ans(int i,int j)//输出子序列
{
if(i==0||j==0)
{
return;
}
if(s1[i-1]==s2[j-1])
{
ans(i-1,j-1);
cout<<s1[i-1];
}
else if(f[i-1][j]>f[i][j-1])
{
ans(i-1,j);
}
else ans(i,j-1);
}
int main()
{
cin>>s1>>s2;
int n=s1.size() ;
int m=s2.size() ;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(s1[i-1]==s2[j-1])
{
f[i][j]=1+f[i-1][j-1];
}
else
{
f[i][j]=max(f[i-1][j],f[i][j-1]);
}
}
}
cout<<f[n][m]<<endl;
ans(n,m);
return 0;
}
|