1446B Catching Cheaters(LCS变形)

1446B Catching Cheaters(LCS变形)

Codeforces Round #683 (Div. 2, by Meet IT)

D. Catching Cheaters

题面Catching Cheaters

题意:给两个字符串 A A A B B B,长度分别为 n n n m m m,定义 S ( C , D ) = 4 ∗ L C S ( C , D ) − ∣ C ∣ − ∣ D ∣ S(C, D) = 4*LCS(C, D) - |C|-|D| S(C,D)=4LCS(C,D)CD,问从 A A A B B B 中各取一个子串能得到最大的 S S S 是多少。

范围 1 ≤ n , m ≤ 5000 1 \le n, m \le 5000 1n,m5000

分析: 显然 L C S LCS LCS 可以进行预处理,从而得到各个子串之间的 L C S LCS LCS,问题主要存在于如何确定两个子串。

如果暴力地在两个字符串中进行选取字符串的话,时间复杂度至少为 O ( n 2 m 2 ) O(n^2m^2) O(n2m2),肯定是不能接受的。但是通过观察可以发现其中存在着类似一维最大子段和的问题,因此只需要处理 A A A 的子串以 i i i 结尾 B B B 的子串以 j j j 结尾的情况,时间复杂度为 O ( n m ) O(nm) O(nm),设计 d p [ i ] [ j ] dp[i][j] dp[i][j] 如下:

A [ i ] = = B [ j ] A[i] == B[j] A[i]==B[j],那么 d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + 4 − 2 = d p [ i − 1 ] [ j − 1 ] + 2 dp[i][j] = dp[i-1][j-1] + 4 - 2 = dp[i-1][j-1]+2 dp[i][j]=dp[i1][j1]+42=dp[i1][j1]+2

A [ i ] ≠ B [ j ] A[i] \ne B[j] A[i]=B[j],那么 d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) − 1 dp[i][j] = max(dp[i-1][j], dp[i][j-1]) - 1 dp[i][j]=max(dp[i1][j],dp[i][j1])1

这是在 L C S LCS LCS 的基础上进行设计的,不过还需要融入最大子段和的思想,因此让所有 d p [ i ] [ j ] ≥ 0 dp[i][j] \ge 0 dp[i][j]0,这样在 d p dp dp 的过程中对于前面对自身没有贡献的部分就完成了剔除。

Code

#include <bits/stdc++.h>
#define int long long
#define double long double
using namespace std;
 
inline int read()
{
    int s = 0, w = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        s = s * 10 + ch - '0', ch = getchar();
    return s * w;
}
 
const int MAXN = 5000 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double eps = 1e-9;
const double PI = acos(-1.0);
 
int n, m, k;
 
int dp[MAXN][MAXN];
 
signed main()
{
    n = read(), m = read();
    string s1, s2;
    cin >> s1 >> s2;
    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            if (s1[i-1] == s2[j-1])
            {
                dp[i][j] = dp[i-1][j-1] + 2;
            }
            else
            {
                dp[i][j] = max(dp[i-1][j], dp[i][j-1]) - 1;
            }
            dp[i][j] = max(0ll, dp[i][j]);
            ans = max(ans, dp[i][j]);
        }
    }
    cout << ans << endl;
    return 0;
}

【END】感谢观看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值