最長共通部分列(LCS)とDP一連の問題に関する研究

LIS問題:
設定\([I] fは\)である([I] \)\と最長の増加系列長末端:
\ [F [I] = F [J] +1し(J <私は&&します[J] <[I]
)\] アレイツリー最適化するために使用され得る(O(nlogn)\)\を

LCSベース順列問題(\(A、B \)が配置されている、すなわち要素が複数回発生していない):
セット\(pos_i \)\(a_iを\)\(B \)の位置が表示され、それ\(a_iを= b_pos_i \)
\(\)サブシーケンス\は(a_p_1、a_p_2、...、 a_p_m \) で\(B \)するための共通のサブシーケンスと同等(pos_p_1を<pos_p_2 <... <\
pos_p_m \) LISを追求することはできます。

LCS一般的な質問:

  1. 古典的な解決策:
    設定\(F [I] [J ] \) を表しのみ考える\(A \)フロント\(Iは\)番目、\(B \)フロント\(J \) A最長の共通部分を配列の長さがある:
    \ [F [I] [J] = \ 1-I] [J-1]とA [I] B = [J] \\&マックス[\開始{}&F整列\を{左。 (F [I-1]〜[ J]、F [i]は[J-1])および[I]!= B [j]は\\ \端{整列} \右。\]

非常にシンプルですが、もう少し複雑であり、より高いアプローチの拡張:

设$f[i][j]$表示只考虑$a$中前$i$个,$b$中前$j$个并且$b_j$已经和$a_1,...,a_i$中的某一个匹配的最长公共子序列长度,有:

\ [F [I] [J ] = \左\ {\開始{整列}&F [I-1]〜[J]と[I]!= B [j]が\\&MAX(F [I-1 ] [K] +1)&
[I] == B [j]は、K <J \\ \端{整列}右\ \] 理由膨張が良いですか?見てくださいこの質問
最長共通部分列上昇に対象にし、あなたはLCSの古典的なソリューションを使用することはできませんが、我々は直接それについて慎重に考えると、我々は上記の伝達方程式を使用している場合、我々は唯一の必要なことがわかっF [I-1(\ ] [K]が\)に移された[I] [J F(\ )] \ 確保するための唯一の必要性、\(B [k]は<B [j]を\) に、私たちは新しい伝達方程式を得る:
\ [ F [I] [J] = \ \ {\ [[J]と[i]を左!= B [j]が\\&MAX(F [I-1] [I-1]整列{開始}&F K] +1)&[I
] == B [j]は、K <J && B [K] <B [j]は\\ \端が{整列} \右。\] とするときので(\ [I] = = B [J] \)場合、\(B [K] <Bは[J] \)と等価である(B [K] <[I] \)\、転送列挙\(J \)の場合すべての\(B [k]は<
コード:

#include<bits/stdc++.h>
using namespace std;
#define N 5007
int f[N],a[N],b[N];
int main()
{
    int i,j,n;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(i=1;i<=n;i++)
        scanf("%d",&b[i]);
    int maxx=0,ans=0;
    for(i=1;i<=n;i++)
    {
        maxx=0;
        for(j=1;j<=n;j++)
        {
            if(b[j]==a[i])f[j]=max(f[j],maxx+1);
            else if(b[j]<a[i])maxx=max(maxx,f[j]);
            ans=max(ans,f[j]);
        }
    }
    printf("%d\n",ans);
    return 0;
}

もちろん、平均LCSの問題のために\(O(nlogn)\)溶液(厳密には)、同じことが、この問題に拡張することができ、我々は最初のピットを残しました。

おすすめ

転載: www.cnblogs.com/lishuyu2003/p/11329708.html