原题链接:Problem - 1446B - Codeforces
题目大意:给你两个字符串A,B,让你分别从A,B中截取子串(连续)C,D,然后这两个串的最长公共子序列长度是LCS(C,D),让你找到最大的4⋅LCS(C,D)−|C|−|D|的值。
思路:这其实是最长公共子序列的变形呜呜我自己还是想不到~
dp[i][j]表示以a[i]结尾b[j]结尾的子串C,D能使4⋅LCS(C,D)−|C|−|D|为最大值的值。
如果a[i] == b[j],那么就由前面的dp[i -1][j - 1]转移过来;
如果a[i] != b[i],就看从dp[i][j - 1]和dp[i - 1][j]哪个转过来划算;如果都不划算,就斩断,dp[i][j]就设为0。
if(a[i] == b[j]) dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 2);
else dp[i][j] = max(0, max(dp[i][j - 1], dp[i - 1][j]) - 1);
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef pair<int, int> PII;
const double pi = acos(-1.0);
#define rep(i, n) for (int i = 1; i <= (n); ++i)
#define rrep(i, n) for (int i = n; i >= (1); --i)
typedef long long ll;
#define sqar(x) ((x)*(x))
const int N = 5010;
int dp[N][N];
char a[N], b[N];
int main()
{
int n, m;
scanf("%d %d", &n, &m);
scanf("%s %s", a + 1, b + 1);
int res = 0;
rep(i, n)
rep(j, m)
{
if(a[i] == b[j]) dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 2);
else dp[i][j] = max(0, max(dp[i][j - 1], dp[i - 1][j]) - 1);
res = max(res, dp[i][j]);
}
printf("%d", res);
return 0;
}