动态规划求解最长公共子序列问题
YOYO
posted @ 2009年4月29日 08:23
in 【算法】与【数据结构】
with tags
动态规划
, 4086 阅读
如果记Ln,m为序列An和Bm的最长公共子序列的长度,则Li,j为序列Ai和Bj的最长公共子序列的长度。根据最长公共子序列的性质,有:
-
#include<iostream>
-
using namespace std;
-
-
#define N 50
-
-
/*
-
* 求最长公共子序列算法
-
*
-
* 输入:字符串a[],字符串b[]
-
* 输出:最长公共子序列c[]及其长度len
-
*/
-
int lcs(char a[], char b[], char c[]){
-
int mz[N+1][N+1],s[N+1][N+1];
-
int n, m;
-
int i, j, k;
-
n = strlen(a), m = strlen(b);
-
-
// 初始化
-
memset(mz,0, sizeof(mz));
-
memset(s, 0, sizeof(s));
-
-
// 计算长度
-
for(i=1; i<=n; i++){
-
for(j=1; j<=m; j++){
-
if(a[i-1]==b[j-1]){ // 若两个字符相等,则是公共子序列的一部分
-
mz[i][j] = mz[i-1][j-1]+1;
-
}else{ // 否则 判断哪个是不需要的字符
-
if(mz[i-1][j]>=mz[i][j-1]){ //若没有a[i]时最长序列大于没有b[j]的
-
mz[i][j] = mz[i-1][j];
-
s[i][j] = -1; // 说明a[i]肯定不在公共子序列中
-
}else{
-
mz[i][j] = mz[i][j-1];
-
s[i][j] = 1; // 反之,说明b[j]肯定不在公共子序列中
-
}
-
}
-
}
-
}
-
-
// 求最长公共子序列字符
-
i = n, j = m;
-
k = mz[n][m];
-
-
c[k--] = '\0';
-
while(i>0&&j>0){
-
switch(s[i][j]){
-
case -1: // 如果为-1,表示a[i]肯定不在,i--
-
i--;
-
break;
-
case 0: // 如果它在公共子序列中,直接存入
-
c[k--] = a[i-1];
-
i--, j--;
-
break;
-
case 1: // 如果为1,表示b[j]肯定不在,j--
-
j--;
-
break;
-
}
-
}
-
-
return mz[n][m];
-
}
-
-
int main(){
-
char a[N],b[N],c[N];
-
while(cin>>a>>b){
-
int len = lcs(a,b,c);
-
cout<<"最长公共子序列是:"<<c<<endl;
-
cout<<"长度为:"<<len<<endl;
-
}
-
return 0;
-
}