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;
}

 

 

 

posted @ 2012-04-14 09:57  gabo  阅读(266)  评论(0编辑  收藏  举报