[JOYOI] 1071 LCIS

拖了好久的LCIS

f[i][j]表示a串前i个,b串以b[j]结尾的LCIS长度。

转移时考虑a[i]和b[j]是否相等,如果不等:

那么既然是以j结尾,说明a串前i-1位有一个字符和b匹配了,所以由f[i-1][j]转移来(i-1涵盖所有方案)

如果相等,那么考虑由什么转移来

f[i-1][k]是一个前驱状态,既然a[i]匹配了,就只能考虑前i-1位了,由于定义如此,所以可以“笼统地”从f[i-1][]转移来,第二维就得枚举j前面的k,且b[k]<b[j],满足递增性质

这样做是O(n^3)的复杂度,考虑优化一下。

对于一个相等的状态,这里O(n)的转移就是优化的瓶颈了,看看怎么做。

f[i][j]只能从f[i-1][k]转移来,k还得小于j,所以可以一边循环j一边用mx记录f[i][1~j-1]的最大值,前提是b[j]>a[i]。

这样转移就可以写成f[i][j]=mx+1了,O(n^2)的复杂度。

第一维可以像01背包一样压下来,空间O(n)

#include<iostream>
#include<cstdio>

using namespace std;

const int MAXN=3005;

inline int rd(){
    int ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c))ret=ret*10+c-'0',c=getchar();
    return ret*f;
}

int n;
int a[MAXN],b[MAXN];

int f[MAXN][MAXN];

int main(){
    n=rd();
    for(int i=1;i<=n;i++) a[i]=rd();
    for(int i=1;i<=n;i++) b[i]=rd();
    for(int i=1;i<=n;i++){
        int mx=0;
        for(int j=1;j<=n;j++){
            if(a[i]>b[j]) mx=max(mx,f[i-1][j]);
            if(a[i]!=b[j]){
                f[i][j]=f[i-1][j];
                continue;
            }
            if(a[i]==b[j]) f[i][j]=mx+1;
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++) ans=max(ans,f[n][i]);
    cout<<ans;
    
    return 0;
}

本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9282854.html

原文地址:https://www.cnblogs.com/ghostcai/p/9282854.html