• [HAOI2010] 最长公共子序列


    求两个字符序列的最长公共子序列以及个数,(nleq 5000)

    Solution

    第一问,考虑 (f[i][j]) 表示两个串分别跑到了 (i,j) 位置的最长公共子序列,则

    [f[i][j]=max(f[i-1][j],f[i][j-1],f[i-1][j-1]+[s[i]==t[j]]) ]

    暴力转移即可

    第二问,考虑 (g[i][j]) 表示两个串分别跑到了 (i,j) 位置的最长公共子序列的方案数,则先正常统计从 (f[i-1][j],f[i][j-1]) 过来的方案数,然后考虑两种特殊情况

    • 如果 (f[i][j]=f[i-1][j-1]) 并且 (s[i] eq t[j]),那么需要额外减去 (g[i-1][j-1])
    • 如果 (f[i][j]=f[i-1][j-1]+1) 并且 (s[i]=t[j]),那么需要额外加上 (g[i-1][j-1])
    #include <bits/stdc++.h>
    using namespace std;
    const int mod = 100000000;
    int n,m,f[2][5005],g[2][5005];
    char s[5005],t[5005];
    
    signed main() {
        cin>>s+1>>t+1;
        n=strlen(s+1);
        m=strlen(t+1);
        --n; --m;
        for(int i=0;i<=n;i++) g[0][i]=1;
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=m;j++) g[i&1][j]=0;
            g[i&1][0]=1;
            for(int j=1;j<=m;j++) {
                f[i&1][j]=max(max(f[i-1&1][j],f[i&1][j-1]),
                            f[i-1&1][j-1]+(s[i]==t[j]));
                if(f[i&1][j]==f[i-1&1][j]) (g[i&1][j]+=g[i-1&1][j])%=mod;
                if(f[i&1][j]==f[i&1][j-1]) (g[i&1][j]+=g[i&1][j-1])%=mod;
                if(f[i&1][j]==f[i-1&1][j-1]&&s[i]!=t[j])
                    (g[i&1][j]+=mod-g[i-1&1][j-1])%=mod;
                if(f[i&1][j]==f[i-1&1][j-1]+1&&s[i]==t[j])
                    (g[i&1][j]+=g[i-1&1][j-1])%=mod;
            }
        }
        cout<<f[n&1][m]<<"
    "<<g[n&1][m]<<endl;
    }
    
    
  • 相关阅读:
    Sort
    RAID
    LeetCode总结 -- 一维动态规划篇
    Count and Say
    Dynamic Programming Introduction
    Mongodb与Redis应用指标对比
    精通有状态vs无状态(Stateful vs Stateless)—Immutable模式之姐妹篇
    Windows 安装 pytorch3d
    GitHub 图片无法显示 或 gist 无法访问
    LaTeX符号表,数学公式速查必备
  • 原文地址:https://www.cnblogs.com/mollnn/p/12390071.html
Copyright © 2020-2023  润新知