[HAOI2010]最長共通部分列 - DP

2つの文字列の最長共通部分列の数を検索し、\(N- \のLeq 5000 \)

解決

最初の質問、考える\(F [i]の[jは ] \) 2つの文字列が走った表し\(I、J \)最長共通部分列の位置、そして
\ [F [i]は[J ] = \ MAX(F [I-1]〜
[J]、F [i]は[J-1]、F [I-1] [J-1] + [S [i]は== T [J])\] 暴力への転送

2番目の質問、考える\(G [i]の[jを ] \) 2つの文字列を表して走った\(I、J \)最長共通サブシーケンスプログラム位置の数、通常からの最初の統計\(F [ ] [J]、F [I I-1]〜[J-1] \) プログラムの数を超えると、2つの特殊なケースを考慮

  • もし\(F [I] [J ] = F [I-1] [J-1] \) と\(S [I] \ NEQ 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]<<"\n"<<g[n&1][m]<<endl;
}

おすすめ

転載: www.cnblogs.com/mollnn/p/12390071.html