基础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