最长公共子序列(DP)(二种数组实现+扩展)

杭电Common Subsequence(1159):

 

题意:

求两个字符串的最大公共子串。

Sample:

abcfbc abfcab

programming contest

abcd mnp

 

4

2

0

 

代码:

#include<iostream>

#include<string.h>

using namespace std;

 

const int MAX = 1000 + 10;

 

char a[MAX];

char b[MAX];

int DP[MAX][MAX];

int Max(int x, int y){               //求最大值

    return x > y ? x : y;

}

 

int main(){

    while(cin>>a>>b){

        int len1 = strlen(a);

        int len2 = strlen(b);

        memset(DP,0,sizeof(DP));                    //初始为0,dp问题必备

         // DP[i][j]表示s1前i个字符与s2的前i个字符的最长公共字串长度

        for(int i=1; i<=len1; i++){

            for(int j=1; j<=len2; j++){ 

                if(a[i-1] == b[j-1])

                    DP[i][j] = DP[i-1][j-1]+1;         //相等时最大长度加1

                else

                    DP[i][j] = Max(DP[i-1][j], DP[i][j-1]);   //不相等时取前面的最大值

            }

        }

        cout<<DP[len1][len2]<<endl;

    }

    return 0;

}

 

 

滚动数组Common Subsequence

#include<iostream>

#include<string.h>

using namespace std;

 

const int maxn = 1000 + 10;

 

int Max (int a, int b){

     return a > b ? a : b;

}

 

char a[maxn];

char b[maxn];

int DP[2][maxn];        //相当用两行的的一维数组,因为每次dp的转换只以前一行相关,所以其它的行可以重新用

 

int main(){

    while(cin>>a>>b){

        int len1 = strlen (a);

        int len2 = strlen (b);

        memset(DP, 0, sizeof(DP));

        for(int i=1; i<=len1; i++){

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

                if(a[i-1]==b[j-1])

                DP[i%2][j]=DP[(i-1)%2][j-1]+1;

            else

                DP[i%2][j]=Max(DP[(i-1)%2][j],DP[i%2][j-1]);

            }

        }

        cout<<DP[len1%2][len2]<<endl;

    }

    return 0;

}

 

 

 

 

(扩展)用公共子串求最大回文串:

#include<iostream>

#include<string.h>

using namespace std;

 

const int maxn = 5000 +10;

int dp[2][maxn];

 

int Max(int a, int b){

    return a > b ? a : b;

}

 

int main(){

    int n;

    while(cin>>n){

        getchar();

        char s1[maxn];

        char s2[maxn];

        gets(s1);

        int len1 = strlen(s1);

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

            s2[len1 - i - 1] = s1[i];

        }

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

        for(int i=1;i<=n;i++){

            for(int j=0;j<=n;j++){

                if(s1[i-1]==s2[j-1]){

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

                }

                else{

                    dp[i%2][j]=Max(dp[(i-1)%2][j],dp[i%2][j-1]);

                }

            }

        }

        //cout<<dp[n%2][n]<<endl;

        cout<<n - dp[n%2][n]<<endl;        //总长度减去最大回文串的值就为最大公共串值

    }

    return 0;

}

posted @ 2013-10-21 08:20  静坐观雨  阅读(373)  评论(0编辑  收藏  举报