zoukankan      html  css  js  c++  java
  • Luogu P2516 [HAOI2010]最长公共子序列 DP

    首先$LIS$显然:$f[i][j]=max(f[i][j-1],f[i-1][j],(a[i]==b[j])*f[i-1][j-1])$

    考虑如何转移数量:

    首先,不管$a[i]$是否等于$b[j]$,

    都有$h[i][j]+=h[i-1][j]*(f[i][j]==f[i-1][j])+h[i][j-1]*(f[i][j]==f[i][j-1])$

    然后讨论$LIS$中第三种转移:

    如果$a[i]==b[j] && f[i][j]==f[i-1][j-1]+1$,有$h[i][j]+=h[i-1][j-1]$

    而如果$a[i]!=b[j] && f[i][j]==f[i-1][j-1]$,有$h[i][j]-=h[i-1][j-1]$,此处是考虑$h[i-1][j]$与$h[i][j-1]$对答案的重复转移,所以要减去;

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define R register int
    using namespace std;
    namespace Fread {
        static char B[1<<15],*S=B,*D=B;
        #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
        inline int g() {
            R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
            do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
        } inline bool isempty(const char& ch) {return ch<=36||ch>=127;}
        inline void gs(char* s) {register char ch; while(isempty(ch=getchar())); do *s++=ch; while(!isempty(ch=getchar()));}
    }using Fread::g; using Fread::gs;
    const int N=500010,M=1E+8;
    int n,m; char s1[N],s2[N];
    int f[2][N],h[2][N];
    signed main() {
        gs(s1+1),gs(s2+1); R l1=strlen(s1+1)-1,l2=strlen(s2+1)-1;
        R c=0; for(R i=0;i<=l2;++i) h[c][i]=1;
        for(R i=1;i<=l1;++i) {
            c^=1; h[c][0]=1;
            for(R j=1;j<=l2;++j) {
                h[c][j]=0;
                f[c][j]=max(f[c^1][j],f[c][j-1]);
                if(s1[i]==s2[j]) f[c][j]=max(f[c][j],f[c^1][j-1]+1);
                if(f[c][j]==f[c^1][j]) h[c][j]+=h[c^1][j];
                if(f[c][j]==f[c][j-1]) h[c][j]+=h[c][j-1];
                if(s1[i]==s2[j]&&f[c][j]==f[c^1][j-1]+1) h[c][j]+=h[c^1][j-1];
                if(s1[i]!=s2[j]&&f[c][j]==f[c^1][j-1]) h[c][j]-=h[c^1][j-1];
                h[c][j]=(h[c][j]+M)%M;
            }
        } printf("%d
    %d
    ",f[c][l2],h[c][l2]);
    }

    2019.07.11

  • 相关阅读:
    测试72.思维好题
    pbds:STL平衡树
    测试69。这场因为轻视少了很多分。
    C++ 中的四种类型转换
    C++ 中的static关键字
    codeforces 1269 E K Integers
    P4556 [Vani有约会]雨天的尾巴 (线段树合并)
    P3521 [POI2011]ROT-Tree Rotations (线段树合并)
    codeforces 600E E. Lomsat gelral (线段树合并)
    线段树合并的一些题
  • 原文地址:https://www.cnblogs.com/Jackpei/p/11170734.html
Copyright © 2011-2022 走看看