题意:给定两个字符串,合并成一个字符串,合并成的这个字符串同时也能分解成原来的两个字符串。
解析:使用DP(LCS最长公共子序列),使用标记,不同的状态,用不同的标记,将公共的字符输出一次即可。
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=1009;
int dp[maxn][maxn];
int vis[maxn][maxn];
char a[maxn];
char b[maxn];
void print(int i,int j)
{
if(!i&&!j)
return;
if(vis[i][j]==0)
{
print(i-1,j-1);
//printf("%d ",i-1);
printf("%c",a[i-1]);
}
else if(vis[i][j]==1)
{
print(i-1,j);
//printf("%d ",i-1);
printf("%c",a[i-1]);
}
else
{
print(i,j-1);
//printf("%d ",j-1);
printf("%c",b[j-1]);
}
}
int main()
{
while(scanf("%s %s",a,b)!=EOF)
{
int lena=strlen(a);
int lenb=strlen(b);
memset(dp,0,sizeof(dp));
for(int i=0;i<=lena;i++)
vis[i][0]=1;
for(int j=0;j<=lenb;j++)
vis[0][j]=-1;
for(int i=1;i<=lena;i++)
{
for(int j=1;j<=lenb;j++)
{
if(a[i-1]==b[j-1])
{
dp[i][j]=dp[i-1][j-1]+1;
vis[i][j]=0;
}
else if(dp[i-1][j]>=dp[i][j-1])
{
dp[i][j]=dp[i-1][j];
vis[i][j]=1;
}
else
{
dp[i][j]=dp[i][j-1];
vis[i][j]=-1;
}
printf("%d %d %d\n",i,j,vis[i][j]);
}
}
//printf("%d\n",dp[lena][lenb]);
print(lena,lenb);
printf("\n");
}
return 0;
}