1 /*给出两串,求一个最小的字符串包含这两个子串,子串在这个字符串中的顺序不变,
2 做法:定义两个数组,分别标记公共部分在第一个串和第二个串中的位置,在输出是判断一下,输出一个串两个公共部分之间的部分,不包含
3 公共部分,在输出第二个串公共部分之间的串,和最后一个公共部分,然后剩下的在公共部分后面的直接输出就可以了,注意这道题不能直接求出
4 最长公共,然后在最短的那个串中删除这个最长公共,剩下的加入第二个串,这样会导致顺序不对*/
5 #include<stdio.h>
6 #include<string>
7 #include<string.h>
8 #include<iostream>
9 using namespace std;
10 const int maxn=110;
11 int dir[maxn][maxn],dp[maxn][maxn];
12 char ida[maxn],idb[maxn];
13 int num;
14 char a[maxn],b[maxn];
15 void LCS(int n,int m)
16 {
17 int i,j;
18 memset(dp,0,sizeof(dp));
19 memset(dir,0,sizeof(dir));
20 for(i=1;i<=n;i++)
21 for(j=1;j<=m;j++)
22 {
23 if(a[i-1]==b[j-1])
24 {
25 dp[i][j]=dp[i-1][j-1]+1;
26 dir[i][j]=1;
27 }
28 else if(dp[i-1][j]>dp[i][j-1])
29 {
30 dp[i][j]=dp[i-1][j];
31 dir[i][j]=0;
32 }
33 else
34 {
35 dp[i][j]=dp[i][j-1];
36 dir[i][j]=2;
37 }
38 }
39 }
40 void print(int n,int m)
41 {
42 if(n==0 || m==0) return;
43 if(dir[n][m]==1)
44 {
45 print(n-1,m-1);
46 ida[num]=n-1;
47 idb[num++]=m-1;
48 }
49 else if(dir[n][m]==0) print(n-1,m);
50 else print(n,m-1);
51 }
52 int main()
53 {
54 int i,j,m,n,k;
55 while(cin>>a>>b)
56 {
57 n=strlen(a);
58 m=strlen(b);
59 memset(ida,0,sizeof(ida));
60 memset(idb,0,sizeof(idb));
61 num=0;
62 LCS(n,m);
63 print(n,m);
64 for(i=0,j=0,k=0;k<num;k++)
65 {
66 //printf("%d %d\n",ida[k],idb[k]);
67 for(;i<ida[k];i++)//输出两个重复字符之间的串
68 printf("%c",a[i]);
69 i++;//跳过公共部分,避免下面的重复输出
70 for(;j<idb[k];j++)
71 printf("%c",b[j]);
72 printf("%c",b[j++]);//输出公共的部分
73 }
74 while(i<n) printf("%c",a[i++]);
75 while(j<m) printf("%c",b[j++]);
76 printf("\n");
77 }
78 return 0;
79 }