zoukankan      html  css  js  c++  java
  • CF1446B

    Solution:

    根据题目描述我们可以知道一个事情,就是每当字符串 (a)(b) 只要子串中多一位,那么答案就会少一,如果匹配的子序列多一个字母,那么答案就会多二。以此我们就可以设计出一个 (dp) 状态,(f[i][j]) 表示以字符串 (a) 的第 (i) 个位置为结尾和以字符串 (b) 的第 (j) 个位置为结尾答案最大是多少。可以得到一个转移方程:

    (f[i][j]=maxegin{cases}0\f[i-1][j]-1\f[i][j-1]-1\f[i-1][j-1]+2;,;a[i]=b[j]end{cases})

    (0) 就表示两个子串中最长公共子序列长度为 (0) (f[i-1][j]-1) 表示从字符串 (a) 中增加一位到 (f[i][j])(f[i][j-1]-1) 与上面同理,(f[i-1][j-1]+2;,;a[i]=b[j]) 表示当字符串 (a)(b) 的第 (i) 和 第 (j) 位相同时,对答案贡献为 (2) .

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        while(c<'0' || c>'9'){if(c=='-') f=0;c=getchar();}
        while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
        return f?x:-x;
    }
    const int N=5010;
    int n,m,f[N][N],ans;
    char a[N],b[N];
    int main()
    {
        n=read(),m=read();
        scanf("%s
    %s",a+1,b+1);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                f[i][j]=max({0,f[i-1][j]-1,f[i][j-1]-1});
                if(a[i]==b[j]) f[i][j]=max(f[i][j],f[i-1][j-1]+2);
                ans=max(ans,f[i][j]);
            }
        }
        printf("%d",ans);
        return 0;
    }
    
  • 相关阅读:
    【水】希望之花
    如何不用狄利克雷卷积证明莫比乌斯函数性质二
    【数学】gcd
    挂分宝典
    [luogu P6042]「ACOI2020」学园祭 题解
    [luogu P6041]「ACOI2020」布丁暗杀计划 题解
    11.19模拟
    「CSP-S2020」题解
    11.11模拟
    「洛谷P1445」樱花
  • 原文地址:https://www.cnblogs.com/ForeverOIer/p/14169985.html
Copyright © 2011-2022 走看看