最長の共通昇順サブシーケンス(LCIS)

題名:

最も長い一般的な昇順のサブシーケンスを見つける

回答:

最長共通昇順サブシーケンス=最長共通サブシーケンス(LCS)および最長昇順サブシーケンス(LIS)
LCSコアコード:

	for(int i=1;i<=n;i++)
	{
    
    
		for(int j=1;j<=m;j++)
		{
    
    
			if(a[i]==b[j])dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
			else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
		}
	}

LISコアコード:

	for(int i=1;i<=n;i++)
	{
    
    
		dp[i]=1;
		for(int j=1;j<i;j++)
		{
    
    
			if(a[j]<a[i])dp[i]=max(dp[i],dp[j]+1);
		}
		mx=max(mx,dp[i]);
	}

最長共通昇順サブシーケンスのコードは、最長共通サブシーケンスで最長昇順サブシーケンスを見つけることです。つまり、a [i] = = b [j]を判断することを前提として、昇順のシーケンス
f [i] [j]を見つけて、すべてのa [1〜i]およびb [1〜j]を表します。 j]最後にあるパブリック昇順サブシーケンスのセット
。f[i] [j]の値は、セットのサブシーケンスの最大長に等しい。
複雑さO(n 3
コード:

for (int i = 1; i <= n; i ++ )
{
    
    
    for (int j = 1; j <= n; j ++ )
    {
    
    
        f[i][j] = f[i - 1][j];
        if (a[i] == b[j])
        {
    
    
            int maxv = 1;
            for (int k = 1; k < j; k ++ )
                if (a[i] > b[k])
                    maxv = max(maxv, f[i - 1][k] + 1);
            f[i][j] = max(f[i][j], maxv);
        }
    }
}

コードを詳しく見てみましょう。forループの第3レベルは、a [i]未満の最長の共通昇順サブシーケンス+1の長さを見つけるために使用されます。実際、知る必要があるのは最長の共通です。長さの前に昇順のサブシーケンス。変数valを使用して最大値をF [i-1] [k]に格納できるため、ループの3番目のレイヤーを省略できます。

for (int i = 1; i <= n; i ++ )
    {
    
    
        int maxv = 1;
        for (int j = 1; j <= n; j ++ )
        {
    
    
            f[i][j] = f[i - 1][j];
            if (a[i] == b[j]) f[i][j] = max(f[i][j], maxv);
            if (a[i] > b[j]) maxv = max(maxv, f[i - 1][j] + 1);
        }
    }

次元を1次元に縮小することもできます
。f[i] [j]はf [i-1] [j]から導出されることがわかっています。f[i]
を使用してシーケンスの最初のi要素を表します。bシーケンス(LCIS)の長さ、tは最長のLCISの終了要素の位置であり、新しい伝達方程式:
f [i] = f [t] +1(a [i] = b [j])
これは1になります。寸法

for(int i=1;i<=n;i++){
    
    
        maxx=0;
        for(int j=1;j<=n;j++){
    
    
            if(b[j]<a[i]&&maxx<f[j]) maxx=f[j];
            if(b[j]==a[i]) f[j]=maxx+1;
        }
    }

コード:

2次元空間のコード:
ここに画像の説明を挿入

#include <cstdio>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 3010;

int n;
int a[N], b[N];
int f[N][N];

int main()
{
    
    
    scanf("%d", &n);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &b[i]);

    for (int i = 1; i <= n; i ++ )
    {
    
    
        int maxv = 1;
        for (int j = 1; j <= n; j ++ )
        {
    
    
            f[i][j] = f[i - 1][j];
            if (a[i] == b[j]) f[i][j] = max(f[i][j], maxv);
            if (a[i] > b[j]) maxv = max(maxv, f[i - 1][j] + 1);
        }
    }

    int res = 0;
    for (int i = 1; i <= n; i ++ ) res = max(res, f[n][i]);
    printf("%d\n", res);

    return 0;
}

1次元配列のコード:
ここに画像の説明を挿入

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<string>
#define ll long long
#define maxn 3050
#define inf 2147483647
#define mod 10003
#define eps 1e-6
#define pi acos(-1.0)
#define de(x) ((x)*(x))
using namespace std; 
inline int read(){
    
    
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {
    
    if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)) {
    
    x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int n,a[maxn],b[maxn],f[maxn],maxx;
signed main(){
    
    
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<=n;i++) b[i]=read();
    for(int i=1;i<=n;i++){
    
    
        maxx=0;
        for(int j=1;j<=n;j++){
    
    
            if(b[j]<a[i]&&maxx<f[j]) maxx=f[j];
            if(b[j]==a[i]) f[j]=maxx+1;
        }
    }
    maxx=0;
    for(int i=1;i<=n;i++) if(maxx<f[i]) maxx=f[i];
    printf("%d",maxx);
    return 0;
}

おすすめ

転載: blog.csdn.net/qq_35975367/article/details/114334425