zoukankan      html  css  js  c++  java
  • LCIS 最长上升公共子序列问题

    首先点名一个串叫 L1,另一个叫L2。

    明显的是一个DP,那么我们来探讨下如何求得答案。

    朴素的算法

    首先我们定义状态$dp[ i ][ j ]$表示L1中前i个与L2中前j个的最长公共上升子序列。

    最外层枚举i,第二层枚举j,那么L1[i]和L2[j]要么相等,要么不相等,分情况讨论。

    ■ L1[i]=L2[j] 那么我们以当前L1[i]的大小作为某个公共上升子序列的结尾元素,所以我们就需要向前找比这个结尾元素小的元素来接头,就需要找到dp[i-1][k] $(k<j&&a[k]<a[j])$中的最长的公共上升子序列的长度,然后其数列长度+1,就是现在dp[i][j]的值。

    ■ L[1]!=L2[j]那么这时候我们则需要继承前边最长的序列长度$dp[i][j]=max(dp[i-1][1->j-1])$.

    这样的时间复杂度$O(n^2 imes m)$,空间复杂度$O(n imes m)$,比较朴素的一中做法。

    代码自行脑补吧。。。。

    优化

    我们来优化一下上边的算法。

    我们每个数在计算的时候,这一行前边的数我们已经都计算过了,在这之间我们完全可以用maxn记录一下最大值,避免再去循环枚举k,直接用maxn就好了。

    时间复杂度$O(n imes m)$

    void LCIS(){
        memset(F,0,sizeof(F));
        for(int i=1;i<=n;i++){
            LL maxn = 0;
            for(int j=1;j<=m;j++){
                F[i][j] = F[i-1][j];
                if(a[i]>b[j] && maxn < F[i-1][j]) maxn = F[i-1][j];
                if(a[i] == b[j]) 
                F[i][j] = maxn+1;
            }
        }
        LL maxn = 0;
        for(int j=1;j<=m;j++){
            if(maxn < F[n][j]) maxn = F[n][j];
        }
        printf("%lld
    ",maxn);
    }

    空间复杂的也可以通过压维进行优化。

    对于每次dp[i][j]的改变我们只需要dp[i-1][1->j-1]中的最大值,压维以后,我们只需要dp[i][1->j-1]中的最大值,同样maxn记录就好了。

    你可能会问:

    每次我们查询后边的都会用到前边的,前边的改变后对后边的不会有影响么?

    不会,因为我们只需要最大值,在这个数改变之前,进行最大值的替换,当它改变后对后边计算没有任何影响。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    int T,n,m,f[100006],a[100006],b[100006],ans;
    int max(int a,int b){ return a>b?a:b; }
    int main()
    {
        freopen("codes.in","r",stdin);
        freopen("codes.out","w",stdout);
        scanf("%d",&T);
        while(T--)
        {
            ans=0;
            scanf("%d",&n);
            for(int i=1;i<=n;i++)scanf("%d",&a[i]);
            scanf("%d",&m);
            for(int i=1;i<=m;i++)scanf("%d",&b[i]);
            memset(f,0,sizeof(f));
            for(int i=1;i<=n;i++)
            {
                int maxn=0;
                for(int j=1;j<=m;j++)
                {
                    if(a[i]>b[j])maxn=max(maxn,f[j]);
                    if(a[i]==b[j])f[j]=maxn+1;
                    ans=max(ans,f[j]);
                }
            }
            printf("%d
    ",ans);
        }
        fclose(stdin);fclose(stdout);
    }
  • 相关阅读:
    常见问题:bootstrap datepicker日期插件汉化
    好的插件
    问题11:web前端开发规范手册(转)
    问题10:获取当前页面宽度JS
    SQL学习1:基础
    问题9:tabtle 整理
    Exception in thread "RMI TCP Connection(idle)" java.lang.OutOfMemoryError: PermGen space
    测试markdown 博客功能
    Cannot generate SSPI context
    Ubuntu 13 Zookeeper 集群配置
  • 原文地址:https://www.cnblogs.com/rmy020718/p/9581514.html
Copyright © 2011-2022 走看看