1、唉,这一道又做了好久好久啊~
2、其实也没有什么,最长公共子序列的变体,但是唯一有难度的就是要输出所求序列,这就需要记录“规划方向”,二维的规划方向比一维的要难,不过理解了就好了,三个方向用0,-1,1表示。
3、注意记录方向的语句是无条件执行的,不是大于ans的时候才执行。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char s[40];
char s1[110][40],s2[110][40];
int d[110][110];
int fa[110][110];
bool flag=false;
int dp(int i,int j){
if(i<0||j<0) return 0;
int &ans=d[i][j];
if(ans>=0)return ans;
ans=0;
if(strcmp(s1[i],s2[j])==0)
{
fa[i][j]=1;
ans=dp(i-1,j-1)+1;
}
else{
if(dp(i,j-1)>dp(i-1,j)){
fa[i][j]=-1;
ans=d[i][j-1];
}
else{
fa[i][j]=0;
ans=d[i-1][j];
}
}
return ans;
}
void print(int i,int j){
if(i<0||j<0) return;
if(fa[i][j]==1){
print(i-1,j-1);
if(flag) printf(" ");
else flag=1;
printf("%s",s1[i]);
}
else if(fa[i][j]==-1){
print(i,j-1);
}
else if(fa[i][j]==0)
print(i-1,j);
return;
}
int main()
{
//freopen("a.txt","r",stdin);
int i,j;
i=0;j=0;
memset(s,'\0',sizeof(s));
while(scanf("%s",s)==1){
if(s[0]!='#') strcpy(s1[i++],s);
else{
while(scanf("%s",s)==1){
if(s[0]!='#') strcpy(s2[j++],s);
else{
memset(d,-1,sizeof(d));
flag=false;
dp(i-1,j-1);
print(i-1,j-1);
printf("\n");
i=0;j=0;memset(s,'\0',sizeof(s));
break;
}
}
}
}
return 0;
}