hdu 1159 dp(最长公共子序列)

在这附一个别人的网址,是求LCS时的空间优化

http://blog.sina.com.cn/s/blog_7826c4dd01011em0.html

 

我贴两个代码,空间复杂度分别为 O(2*n)的和O(n)的

 

空间复杂度O(2*n)
//hdu 1159  dp(最长公共子序列)

//以下是空间复杂度为O(2*n)的代码

#include <stdio.h>

#include <string.h>

#include <algorithm>



using namespace std;



#define N 3000



char tmp1[N], tmp2[N];

//这里本来应该是 dp[N][N]的,应为求LCS时,用第一串的

//第i 个字符与第二串匹配时,时从前一个字符跟第二串每个字符匹配

//得到的最优值转移过来的,具体看下面代码和注释

int dp[2][N];



int LCSL(char *t1, char *t2)

{

    memset(dp, 0, sizeof(dp));

    int len1= strlen(t1), len2 = strlen(t2);

    //求LCSL时就是

    for(int i = 0; i < len1; ++i)

    {   //第一串 的 i字符和第二串的 j字符匹配时

        for(int j = 0; j < len2; ++j)

        {  //若匹配成功,则dp[i][j] = dp[i-1][j-1]+1,意思是从

           //t1的 前 i-1个字符和t2串的 前 j-1个字符匹配中最优值+1

            if(t1[i] == t2[j])  //这里本可以(i-1)&1 可是i从0开始所以(i+1)&1也一样

                dp[i&1][j] = dp[ (i+1)&1 ][j-1] + 1;

            else    //若匹配不成功,则取 t1第i个 和t2第j-1个匹配时的最优值或i-1 和 j匹配

                dp[i&1][j] = max(dp[i&1][j-1], dp[ (i+1)&1 ][j]);//时的最优值 中的最大值

        }

    //在求c(i,j)时,只用到了c(i-1,j)和c(i,j-1),所以可以用滚动数组来优化



    }

    return dp[(len1-1)&1][len2-1];

}



int main()

{

    while(scanf("%s%s", tmp1, tmp2) != EOF)

    {

        printf("%d\n", LCSL(tmp1, tmp2));

    }

    return 0;

}

 

空间复杂度O(n)
//hdu 1159  dp(最长公共子序列)

//以下是空间复杂度为O(n)的代码

#include <stdio.h>

#include <string.h>



#define N 3005



int n;

char tmp1[N], tmp2[N];

//这里本来应该是 dp[N][N]的,应为求LCSL时,用第一串的

//第i 个字符与第二串匹配时,时从前一个字符跟第二串每个字符匹配

//得到的最优值转移过来的,具体看下面代码和注释

int dp[N];



int max(int a, int b)

{

    return a > b ? a : b;

}



int LCSL(char *t1, char *t2)

{

    int m, len1 = strlen(t1), len2 = strlen(t2);

    memset(dp, 0, sizeof(dp));



    //求LCS时就是

    for(int i = len1-1; i >= 0; --i)

    {   //第一串 的 i字符和第二串的 j字符匹配时

        int tmp = 0;    //tmp记录对角线的值,即从前往后推的dp[i-1][j-1]

        for(int j = len2-1; j >= 0; --j)

        {

            m = max(dp[j], dp[j+1]);

            if(t1[i] == t2[j])

            {

                m = max(tmp+1, m);

            }

            tmp = dp[j];    //继续取对角线的值

            dp[j] = m;    //覆盖当前值

        }

    }

    return dp[0];

}



int main()

{

    while(scanf("%s%s", tmp1, tmp2) != EOF)

    {

        printf("%d\n", LCSL(tmp1, tmp2));

    }

    return 0;

}

 

 

 

你可能感兴趣的:(HDU)