B. Catching Cheaters ###K ###K ###K //K
题目链接:https://codeforces.ml/problemset/problem/1446/B
题意:给定2个字符串a,b 求其中的任意子串的贡献值最大 贡献值为4*LCS(a,b )-|a|-|b|
思路:考虑到要n^2 处理 并且还要考虑子串的问题 所以想到dp 定义的状态为dp[i][j] A串以i为结尾B串以j为结尾的最大值
而不是前i个a的字符和前j个b的字符的最大贡献值,因为要求的是子串,只有通过这样的转移分割掉前缀
要区分开普通的LCS 因为LCS求的是子序列所以并不需要分割前缀
转移状态的话 如果a[i]==b[j] 那么dp[i][j]=dp[i-1][j-1]+2 (抵消2个字母再加上4的贡献) 否则的话dp[i][j]=max(dp[i-1][j]-1,dp[i][j-1]-1)
注意不能小于0 这样是类似了最大子段和 用0来把前面没有贡献的多余部分给去掉
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pb push_back 5 const int mod=1e9+7; 6 const int maxn=5e3+10; 7 int dp[maxn][maxn]; 8 9 10 int main() 11 { 12 ios::sync_with_stdio(0); 13 cin.tie(0); 14 int n,m; 15 cin>>n>>m; 16 string a,b; 17 cin>>a>>b; 18 int ans=0; 19 for(int i=1;i<=n;i++) 20 { 21 for(int j=1;j<=m;j++) 22 { 23 if(a[i-1]==b[j-1]) 24 { 25 dp[i][j]=dp[i-1][j-1]+2; 26 } 27 else 28 dp[i][j]=max({0,dp[i-1][j]-1,dp[i][j-1]-1}); 29 ans=max(ans,dp[i][j]); 30 } 31 } 32 cout<<ans<<'\n'; 33 34 35 36 37 38 39 }
dp 求LCS的代码
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define pb push_back 4 using namespace std; 5 const int maxn=1e3+10; 6 const int mod=1e9+7; 7 int a[maxn],b[maxn]; 8 int dp[maxn][maxn]; 9 10 11 int main() 12 { 13 ios::sync_with_stdio(0); 14 cin.tie(0); 15 int n; 16 cin>>n; 17 for(int i=1;i<=n;i++) 18 { 19 cin>>a[i]; 20 } 21 for(int i=1;i<=n;i++) 22 { 23 cin>>b[i]; 24 } 25 //dp[i][j] a串的前i位到b串的前j位的最大值 26 for(int i=1;i<=n;i++) 27 { 28 for(int j=1;j<=n;j++) 29 { 30 dp[i][j]=max(dp[i-1][j],dp[i][j-1]); 31 if(a[i]==b[j]) 32 dp[i][j]=dp[i-1][j-1]+1; 33 } 34 } 35 cout<<dp[n][n]<<'\n'; 36 37 38 39 40 41 }

浙公网安备 33010602011771号