题目大意
思路:
定义DP[i][j]为以Ai和Bi作为结尾点的最大的答案(LCS(C,D)*4-|C|-|D|),显然允许公共子序列为空,这样DP[i][j]=0.
有两种转移方式:
1.Ai==Bj,则DP[i][j]=min(DP[i][j],DP[i-1][j-1]+2),因为以Ai和Bj结尾的两个连续子串C和D的公共子序列的长度+1,同时两个连续子串C和D的长度+1,因此对答案的贡献就+2.
2.Ai!=Bj,DP[i][j]=max(DP[i][j],max(dp[i][j-1],DP[i-1][j])-1),因为以Ai和Bj结尾的两个连续子串C和D的公共子序列的长度不变,但是连续子串C或者D的长度+1,因此对答案的贡献-1
PS:为什么情况2不会影响最优答案的形成?
由于情况2永远不会获得更大的LCS,它对答案的贡献也是越来越少。并且我们得到的答案一定是由情况1形成的。情况二只是针对部分C、D之间一段不存在公共子序列的情况,当到达情况一的时候并结合之前的贡献总和从而使得答案增大。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=5000+50;
int dp[maxn][maxn],n,m;char A[maxn],B[maxn];
int main(){
cin>>n>>m>>A+1>>B+1;int len1=strlen(A+1),len2=strlen(B+1);
int ans=0;
for(int i=1;i<=len1;i++){
for(int j=1;j<=len2;j++){
if(A[i]==B[j]){
dp[i][j]=max(dp[i][j],max(dp[i-1][j-1]+2,2));
}
else{
dp[i][j]=max(dp[i][j],max(dp[i-1][j]-1,dp[i][j-1]-1));
}
ans=max(ans,dp[i][j]);
}
}
cout<<ans<<endl;
return 0;
}