微软面试题 之 "Longest Common Sequence"

求两个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;
}
posted on 2006-04-10 22:17  万俊峰Kevin  阅读(1158)  评论(4编辑  收藏  举报