基础DP(3)

  • 最长公共子序列(LCS)

放题:

http://acm.hdu.edu.cn/showproblem.php?pid=1159

首先,子序列是在给定序列中删去若干元素后得到的序列,例如X=(A,B,C,D,E),那么(A,B,D)就是X的子序列,那(A,B,D)是子串吗?不是,子串的元素在原序列中是连续的。给定两个序列X,Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。最长公共子序列是长度最长的子序列。

用L[i][j]表示子序列Xi和Yj的最长公共子序列的长度。

当Xi=Yj时,找X(i-1)和Y(j-1)的最长公共子序列,然后在尾部加上Xi(对于序列长度来说就是+1)。

当Xi≠Yj时,取X(i-1)和Yj最长公共子序列与Xi和Y(j-1)最长公共子序列的较大值。(所以输出方案时从后往前递推)

代码:

#include<bits/stdc++.h>
using namespace std;

int dp[1005][1005];
string str1,str2;

int LCS(){
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=str1.length();i++){
        for(int j=1;j<=str2.length();j++){
            if(str1[i-1]==str2[j-1])//因为dp[i][j]要通过dp[i-1][j-1]求出,所以i和j从1开始,比较的子序列应该时i-1和j-1
            dp[i][j]=dp[i-1][j-1]+1;//上述的两种情况
            else
            dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
        }
    }
    return dp[str1.length()][str2.length()];
}
int main()
{
    while(cin>>str1>>str2){
        cout<<LCS()<<endl;
    }
    return 0;
 } 

要求输出具体方案时,同样可以用滚动数组减少空间复杂度,和0/1背包相同。

 EOF

原文地址:https://www.cnblogs.com/Untergehen/p/14327843.html