如果记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;
- }