给定两个序列X=<x1,x2,x3,x4…xm>和Y=<y1,y2,y3,y4…yn>,求X和Y长度最长的公共子序列。
可以用动态规划的方法解决这个问题,建立数组c[i][j],i和j分别表示Xi 和Yj的的LCS长度,如果i=0,j=0,c[i][j]=0,根据最优子结构的性质,得到问题的递推公式为:
建立数组b[i][j],如果b[i][j]=0,代表c[i][j]=c[i-1][j-1]+1的情况,如果b[i][j]=-1,代表c[i][j]=c[i][j-1]的情况,如果b[i][j]=1,代表c[i][j]=c[i-1][j]的情况。数组b[i][j]在递归地构造LCS时会用到。
程序为:
# include <stdio.h> # include <stdlib.h> # include <string.h> # define N 100 int main() { int f1(char *a,char *b,int c[][N],int d[][N]); void print(int b[][N],char *a,int i,int j); char a[20]="abcrty"; char b[20]="aerbtyc"; int c[N][N]; int d[N][N]; int i,j; char *s=0; f1(a,b,c,d); print(d,a,strlen(a),strlen(b)); system("pause"); return 0; } int f1(char *a,char *b,int c[][N],int d[][N]) { int lena=strlen(a); int lenb=strlen(b); int i=0; int j=0; for(i=0;i<=lena;i++) //c[i][j]的初始化 c[i][0]=0; for(j=0;j<=lenb;j++) c[0][j]=0; for(i=1;i<=lena;i++) //递推公式 for(j=1;j<=lenb;j++) { if(a[i-1]==b[j-1]){ c[i][j]=c[i-1][j-1]+1; d[i][j]=0; } else if(c[i-1][j]>c[i][j-1]){ c[i][j]=c[i-1][j]; d[i][j]=1; } else { c[i][j]=c[i][j-1]; d[i][j]=-1; } } return 0; } void print(int b[][N],char *a,int i,int j) //递归的方法构造LCS { if(i==0||j==0) return ; if(b[i][j]==0){ print(b,a,i-1,j-1); printf("%c\t",a[i-1]); } else if (b[i][j]==1) print(b,a,i-1,j); else print(b,a,i,j-1); }
上面的代码使用了附加空间b数组,在构造LCS时采用了递归,因为程序的效率较低,对上面的代码稍作优化,不使用数组b,构造用循环的方式构造LCS。代码如下:
# include <stdio.h> # include <stdlib.h> # include <string.h> # define N 100 int main() { int f(char *a,char *b,int c[][N]); char * lcs(char s[],char *a,char *b,int c[][N]); char a[20]="abcrty"; char b[20]="aerbtyc"; int c[N][N]; int d[N][N]; int i,j; char *s=0; f(a,b,c); s=lcs(s,a,b,c); printf("%s\n",s); system("pause"); return 0; } int f(char *a,char *b,int c[][N]) { int lena=strlen(a); int lenb=strlen(b); int i=0,j=0; for(i=0;i<=lena;i++) //初始化 c[i][0]=0; for(j=0;j<=lenb;j++) c[0][j]=0; for(i=1;i<=lena;i++) //递推公式 for(j=1;j<=lenb;j++) { if(a[i-1]==b[j-1]) c[i][j]=c[i-1][j-1]+1; else if(c[i-1][j]>c[i][j-1]) c[i][j]=c[i-1][j]; else c[i][j]=c[i][j-1]; } return c[lena][lenb]; } char * lcs(char s[],char *a,char *b,int c[][N]) { int i=strlen(a); int j=strlen(b); int k=f(a,b,c); s=(char *)malloc(k*sizeof(char)); s[k]=‘\0‘; while(k>0) { if(c[i][j]==c[i-1][j]) i--; else if(c[i][j]==c[i][j-1]) j--; else { s[--k]=a[i-1]; i--;j--; } } return s; //最长公共子序列 }
原文:http://blog.csdn.net/u011608357/article/details/24527057