【HDU】 1159 Common Subsequence
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1159
现在逐渐对dp开始有感觉了。
本题dp的思路大约来自于最初学习最长不降子序列的思想,以一个字符串为基准,另一个字符串在匹配过程中用一个dp数组去记录当前位置的最优状态。dp问题最难的在于转移方程。我们想象下,dp数组中记录了从匹配起始到该点最大的匹配长度,那么每次遇见str[i]==str[j]的时候,dp值肯定要在前面的基础上累加;而如果不相同的话,取前面最大的。
这里说的“前面”还是一个很模糊的概念,因为涉及到两个字符串,那么前面究竟是那个呢?
第一个是不相等的情况:取两个叉线中的最大值,因为每次都要取到目前这个状态的最优情况,那么到目前 i <-> j 之前的状态肯定是 i-1 <-> j 和 i <-> j-1.
第二个是相等的情况:他前面的情况就是i-1 <-> j-1.
Common Subsequence
1 /* 2 最长不降子序列的改编版,其实本质也是dp 3 当沿着两个字符串进行匹配的时候每次都记录当前位置的最优状态,并适时更新; 4 即: 5 1、当str1[i]==str2[j]:dp[i][j] = dp[i-1][j-1]+1; 6 2、否则:dp[i][j] = max(dp[i-1][j] ,dp[i][j-1]); 7 */ 8 #include <iostream> 9 #include <cstdio> 10 #include <cstdlib> 11 #include <cstring> 12 #include <string> 13 #include <cmath> 14 #include <algorithm> 15 #include <iomanip> 16 #define MAXN 1001 17 using namespace std; 18 char pat[MAXN], sub[MAXN]; 19 int dp[MAXN][MAXN]; 20 21 int main() 22 { 23 int i, j, lena, lenb; 24 while(~scanf("%s %s",pat,sub)){ 25 lena = strlen(pat); 26 lenb = strlen(sub); 27 memset(dp,0,sizeof(dp)); 28 for(i=1; i<=lena; ++i){ 29 for(j=1; j<=lenb; ++j){ 30 if(pat[i-1] == sub[j-1]) dp[i][j] = dp[i-1][j-1]+1; 31 else dp[i][j] = dp[i-1][j] > dp[i][j-1] ? dp[i-1][j] : dp[i][j-1]; 32 } 33 } 34 35 printf("%d\n",dp[lena][lenb]); 36 } 37 return 0; 38 }