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 ",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(" "); 77 } 78 return 0; 79 }