题目链接:传送门
题目思路:
如果这道题,没有让求出所有子串的的这个值(定义为X),那么显然是可以直接求LCS*4 然后最后减去( |A| + |B| );
现在设计状态 :f[i][j] 表示以i ,j 为结尾的子串最大的X;
状态转移方程:
if s[i]==t[j] then f[i][j]=max( f[i][j] , f[i-1][j-1] + 2 );
if s[i] !=t[j] then f[i][j]=max( 0 , f[i][j-1] - 1 , f[i-1][j] - 1 ); ps: f[i][j] <- f[i-1][j] , |C|增加1 ,LCS没有增加,因此总体是 减1
根据最大子段和的思想,如果前一段的和为负了,那么前一段对最终答案的贡献也一定是负贡献,因此可以舍掉前一段并令 sum = 0;这里同理 ,如果以i ,j 为结尾的子串最大的X 为负数,其贡献也是负数,因此可以舍掉,则 f[i][j] = 0 ,相当于 以 i,j 为结尾的最优子串是空串。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 typedef unsigned long long uLL; 5 typedef pair<int,int> pii; 6 typedef pair<LL,LL> pLL; 7 typedef pair<double,double> pdd; 8 const int N=5e3+5; 9 const int M=1e7+5; 10 const int inf=0x3f3f3f3f; 11 const LL mod=1e9+7; 12 const double eps=1e-8; 13 const long double pi=acos(-1.0L); 14 #define ls (i<<1) 15 #define rs (i<<1|1) 16 #define fi first 17 #define se second 18 #define pb push_back 19 #define eb emplace_back 20 #define mk make_pair 21 #define mem(a,b) memset(a,b,sizeof(a)) 22 LL read() 23 { 24 LL x=0,t=1; 25 char ch; 26 while(!isdigit(ch=getchar())) if(ch=='-') t=-1; 27 while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); } 28 return x*t; 29 } 30 int f[N][N]; 31 char s[N],t[N]; 32 int main() 33 { 34 int T=1;//最大子段和,如果前一段小于0那么贡献肯定为负数,直接舍去 35 while(T--) 36 { 37 int n=read(),m=read(); 38 scanf("%s%s",s+1,t+1); 39 int ans=0; 40 for(int i=1;i<=n;i++) 41 { 42 for(int j=1;j<=m;j++)//f数组默认全0 43 { 44 if(s[i]==t[j]) f[i][j]=max(f[i][j],f[i-1][j-1]+2); 45 else 46 { 47 f[i][j]=max(f[i][j],f[i-1][j]-1); 48 f[i][j]=max(f[i][j],f[i][j-1]-1); 49 } 50 ans=max(ans,f[i][j]); 51 } 52 } 53 printf("%d ",ans); 54 } 55 return 0; 56 }