动态规划法求两个序列的最长公共子序列问题,MIT的perfessor讲的非常详细,根据他的算法的两种实现
注意,这里所指的最长公共子序列是可以不相邻的,与平常所说的最长公共子串(相邻的)不一样。
#include<stdio.h>
#include<iostream>
using namespace std;
#define max_num(x, y) (x)>(y)?(x):(y)
int c[100][100] = {-1};
int LCS(char a[], char b[], int i, int j)
{
if (i == 0 || j == 0)
c[i][j] = 0;
else if (c[i][j] != -1)
{
if (a[i] == b[j])
{
c[i][j] = LCS(a, b, i-1, j-1) + 1;
}
else
{
int L1 = LCS(a, b, i-1, j);
int L2 = LCS(a, b, i, j-1);
c[i][j] = max_num(L1, L2);
}
}
return c[i][j];
}
int main(int n, char * argv[])
{
char a[] = {'B', 'D', 'C', 'A', 'B', 'A'};
char b[] = {'A', 'B', 'C', 'B', 'D', 'A', 'B'};
int m = sizeof(a)/sizeof(char);
int n = sizeof(b)/sizeof(char);
int len_lcs = LCS(a, b, m, n);
cout<<"max LCS is: "<<len_lcs<<endl;
return 1;
}
//above algorithm can only count the length, below function can get the LCS sequence
#include<stdio.h>
#include<iostream>
using namespace std;
int c[100][100];
int flag[100][100] = {-1}; //it saves the character
int LCS(char a[], char b[], int m, int n)
{
int i, j;
for (i = 0; i <= m; i++)
c[i][0] = 0;
for (j = 0; j <= n; j++)
c[0][j] = 0;
//a[0...m-1], b[0...n-1], c[0,..., m][0,...,n]
for (i = 1; i <= m; i++)
for (j = 1; j <= n; j++)
{
if (a[i-1] == b[j-1])
{
c[i][j] = c[i-1][j-1] + 1;
flag[i][j] = 1;
}
else if (c[i-1][j] >= c[i][j-1])
{
c[i][j] = c[i-1][j];
flag[i][j] = 2;
}
else
{
c[i][j] = c[i][j-1];
flag[i][j] = 3;
}
}
return c[m][n];
}
/************non-recursion print LCS*****************/
void printLCS(int flag[100][100], char a[], int m, int n)
{
int i, j, k;
char res[100];
k = 0;
i = m;
j = n;
while (i > 0 && j > 0)
{
switch(flag[i][j])
{
case 1:
{
res[k++] = a[i-1];
i--;
j--;
break;
}
case 2:
{
i--;
break;
}
case 3:
{
j--;
break;
}
}
}
for (i = k - 1; i >= 0; i--)
cout<<res[i];
cout<<endl;
}
/************recursion print LCS*****************
void printLCS(int flag[][100], char a[], int i, int j)
{
if(i == 0 || j == 0)
return;
if(flag[i][j] == 1)
{
printLCS(flag, a, i-1, j-1);
printf("%c ", a[i-1]);
}
else if(flag[i][j] == 2)
printLCS(flag, a, i-1, j);
else
printLCS(flag, a, i, j-1);
}
*****************************************/
int main(int argc, char * argv[])
{
char a[] = {'B', 'D', 'C', 'A', 'B', 'A'};
char b[] = {'A', 'B', 'C', 'B', 'D', 'A', 'B'};
int m = sizeof(a)/sizeof(char);
int n = sizeof(b)/sizeof(char);
int len_lcs = LCS(a, b, m, n);
cout<<"max LCS is: "<<len_lcs<<endl;
printLCS(flag, a, m, n);
return 1;
}