题目的意图就是考察最长公共子序列,顺带着考察一下这个题目怎么用回溯法输出这个子序列。
#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
char str1[120],str2[120];
int dp[120][120],ko[120][120];
void dfs(int l,int n)
{
if(l==0&&n==0)
return ;
if(ko[l][n]==2)
{
dfs(l-1,n-1);
cout<<str1[l];
}
else if(ko[l][n]==1)
{//str1[l]不参与构成公共子序列,单独输出。
dfs(l-1,n);
cout<<str1[l];
}
else if(ko[l][n]==3)
{//和上面同理。
dfs(l,n-1);
cout<<str2[n];
}
}
int main()
{
int len1,len2,i,j;
while(cin>>str1>>str2)
{
len1=strlen(str1);
len2=strlen(str2);
for(i=len1;i>=1;i--)
str1[i]=str1[i-1];
for(i=len2;i>=1;i--)
str2[i]=str2[i-1];
memset(dp,0,sizeof(dp));
memset(ko,0,sizeof(ko));
//奇葩情况之一,只有第一个字符串没全部用完,根据上面的回溯标记为1,因为你下面是只能输出str1。
for(i=1;i<=len1;i++)
ko[i][0]=1;
//和上面的道理是一样的。
for(i=1;i<=len2;i++)
ko[0][i]=3;
for(i=1;i<=len1;i++)
for(j=1;j<=len2;j++)
{
if(str1[i]==str2[j])
{
dp[i][j]=dp[i-1][j-1]+1;
ko[i][j]=2;
}
else {
if(dp[i][j-1]>dp[i-1][j])
{
//这个是在构成最长公共子序列的时候没有用到str2[j],ko[i][j]标记为3.
dp[i][j]=dp[i][j-1];
ko[i][j]=3;
}
else {
//这个是在构成公共子序列的时候没有用到str1[i],所以这个的ko[i][j]标记为1.
dp[i][j]=dp[i-1][j];
ko[i][j]=1;
}
}
}
dfs(len1,len2);
cout<<endl;
}
return 0;
}