第三遍做这道题,对DP有了更深的理解。动态规划是一种解决问题的方法、途径,最优化原理(principle of optimality),把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解。
说明:动态规划要求其子问题既要独立又要重叠,这初看上去貌似存在矛盾,其实不然。只是这里说的是两个不同的
概念。独立指的是同一问题的两个子问题不共享资源。而重叠子问题指的是子问题可以作为不同的问题的子问题出
现。
设X = <x1,x2...xm>, Y = <y1,y2...yn>为两个序列,并设Z = <z1,z2...zk>为X和Y的任意一个LCS。可以得出:
1、如果xm = yn,那么zk = xm = yn而且Z(k-1)是X(m-1)和Y(n-1)的一个LCS;
2、如果xm != yn,那么zk != xm蕴含Z是X(m-1)和Y的一个LCS;
3、如果xm != yn,那么zk != yn蕴含Z是X和Y(n-1)的一个LCS。
注:上面的Z(k-1)表示序列Z<z1,z2...zn>,其中n=k-1。其它的X()和Y()也是一样的。
很容易证明上述三点是成立的,详细证明见算法导论。所以LCS具有最优子结构。从上面也可以看出LCS问题中的重
叠子问题的性质。所以我们可以用动态规划来解决LCS问题。由LCS问题的最优子结构可得出递归式:
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1000+10; int dp[maxn][maxn]; char a[maxn],b[maxn]; int la,lb; int main(){ cin>>a>>b; la=strlen(a); lb=strlen(b); memset(dp,0,sizeof(dp)); for(int i=1;i<=la;i++) for(int j=1;j<=lb;j++){ if(a[i-1]==b[j-1]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); } int len=dp[la][lb]; stack<char>ans; int i=la,j=lb; while(dp[i][j]){ if(dp[i][j]==dp[i-1][j]) i--; else if(dp[i][j]==dp[i][j-1]) j--; else { ans.push(a[i-1]); i--;j--; } } while(!ans.empty()){ printf("%c",ans.top()); ans.pop(); } return 0; }