求两个string的最长公共子序列
如:
"abcdef", "aabacfe" => "abce"
"swew", "wews" => "wew"
code:
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <time.h>
enum { MAX_LEN = 100 };
void LCS_Aux(const char* s1, int l1, const char* s2, int l2, char* output, int& lo)
{
if (l1 <= 0 || l2 <= 0 || l1 > MAX_LEN || l2 > MAX_LEN)
{
lo = 0;
}
else if (s1[l1-1] == s2[l2-1])
{
LCS_Aux(s1, l1-1, s2, l2-1, output, lo);
output[lo] = s1[l1-1];
lo++;
}
else
{
int len1, len2;
char tmp[MAX_LEN] = {0};
LCS_Aux(s1, l1-1, s2, l2, output, len1);
LCS_Aux(s1, l1, s2, l2-1, tmp, len2);
if (len1 < len2)
{
strncpy(output, tmp, len2);
lo = len2;
}
else
{
lo = len1;
}
}
}
char* LCS_Recursive(const char* s1, const char* s2)
{
if (s1 == 0 || s2 == 0)
return 0;
int len1 = strlen(s1);
int len2 = strlen(s2);
char* output = new char[len1];
memset(output, 0, len1);
int olen = 0;
LCS_Aux(s1, len1, s2, len2, output, olen);
return output;
}
int max(int a, int b)
{
return a > b ? a : b;
}
char* LCS_DP(const char* s1, const char* s2)
{
if (s1 == 0 || s2 == 0)
return 0;
int l1 = strlen(s1);
int l2 = strlen(s2);
if (l1 > MAX_LEN || l2 > MAX_LEN)
return 0;
int m[MAX_LEN][MAX_LEN] = {0};
char d[MAX_LEN][MAX_LEN] = {0};
for (int i = 0; i < l1; ++i)
{
for (int j = 0; j < l2; ++j)
{
if (s1[i] == s2[j])
{
if (i == 0 || j == 0)
{
d[i][j] = '\\';
m[i][j] = 1;
}
else
{
d[i][j] = '\\';
m[i][j] = m[i-1][j-1] + 1;
}
}
else
{
if (i == 0)
{
d[i][j] = '-';
m[i][j] = m[i][j-1];
}
else if (j == 0)
{
d[i][j] = '|';
m[i][j] = m[i-1][j];
}
else
{
if (m[i][j-1] > m[i-1][j])
{
d[i][j] = '-';
m[i][j] = m[i][j-1];
}
else
{
d[i][j] = '|';
m[i][j] = m[i-1][j];
}
}
}
}
}
// Print the matrix
for (int i = 0; i < l1; ++i)
{
for (int j = 0; j < l2; ++j)
{
printf("%d ", m[i][j]);
}
printf("\n");
}
// Print the path
for (int i = 0; i < l1; ++i)
{
for (int j = 0; j < l2; ++j)
{
printf("%c ", d[i][j]);
}
printf("\n");
}
int len = m[l1-1][l2-1];
char* result = new char[len+1];
memset(result, 0, l1);
char* p = result + len;
--l1, --l2;
*p = 0;
while (l1 >= 0 && l2 >= 0)
{
if (d[l1][l2] == '\\')
{
*--p = s1[l1];
--l1, --l2;
}
else if (d[l1][l2] == '-')
{
--l2;
}
else if (d[l1][l2] == '|')
{
--l1;
}
}
return result;
}
int main(int argc, char* argv[])
{
char* input[2][16] =
{
{ "abcdef", "aabacfe", "abce" },
{ "swew", "wews", "wew" },
};
for (int i = 0; i < 2; ++i)
{
time_t start = time(0);
char* result = LCS_Recursive(input[i][0], input[i][1]);
printf("%s\n", result);
assert(strcmp(result, input[i][2]) == 0);
delete[] result;
printf("%u\n\n", time(0)-start);
start = time(0);
result = LCS_DP(input[i][0], input[i][1]);
printf("%s\n", result);
assert(strcmp(result, input[i][2]) == 0);
delete[] result;
printf("%u\n\n", time(0)-start);
}
return 0;
}