最长公共子序列+最长递增子序列+最长递增公共子序列

//求最长公共子序列

int dp[maxn][maxn];
int a[maxn],b[maxn];
int main()
{
    int m,n;
    scanf("%d %d",&m,&n);
    for(int i=1; i<=m; i++)
        scanf("%d",&a[i]);
    for(int i=1; i<=n; i++)
        scanf("%d",&b[i]);
    memset(dp,0,sizeof(dp));
    int ans=0,i,j;
    for(i=1; i<=m; i++)
    {
        for(j=1; j<=n; j++)
        {
            if(a[i]==b[j])
            {
                dp[i][j]=dp[i-1][j-1]+1;
            }
            else
                dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
        }
    }
    printf("%d\n",dp[m][n]);
    return 0;
}

//输出最长公共子序列

int dp[maxn][maxn];
int d[maxn][maxn];
int a[maxn],b[maxn],ans[maxn];
int main()
{
    int m,n;
    int i,j;
    scanf("%d %d",&m,&n);
    for(i=1; i<=m; i++)
        scanf("%d",&a[i]);
    for(i=1; i<=n; i++)
        scanf("%d",&b[i]);
    for(i=0;i<=m;i++)
        dp[i][0]=0;
    for(i=0;i<=n;i++)
        dp[0][i]=0;
    for(i=1; i<=m; i++)
    {
        for(j=1; j<=n; j++)
        {
            if(a[i]==b[j])
            {
                dp[i][j]=dp[i-1][j-1]+1;
                d[i][j]=3;
            }
            else
            {
                if(dp[i-1][j]>=dp[i][j-1])
                {
                    dp[i][j]=dp[i-1][j];
                    d[i][j]=2;
                }
                else
                {
                    dp[i][j]=dp[i][j-1];
                    d[i][j]=1;
                }
            }
        }
    }
    i=m,j=n;
    int k=dp[m][n]-1;
    while(k>=0&&i>0&&j>0)
    {
        if(d[i][j]==3)
        {
            ans[k--]=a[i];
            i--;
            j--;
        }
        else if(d[i][j]==2)
            i-- ;
        else if(d[i][j]==1)
            j--;
        else
            break;
    }
    printf("%d\n",dp[m][n]);
    for(i=0;im][n];i++)
        printf("%d ",ans[i]);
    printf("\n");
    return 0;
}

//求最长上升子序列

int a[maxn],dp[maxn];
int main()
{
    int m;
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
        scanf("%d",&a[i]);
    int res=0;
    for(int i=1;i<=m;i++)
    {
        dp[i]=1;
        for(int j=1;jif(a[j]1);
            }
        }
        res=max(res,dp[i]);
    }
    printf("%d\n",res);
    return 0;
}

//最长上升子序列优化(利用二分查找lower_bound()函数)
//查找优化到0(log(n))

int a[maxn],dp[maxn];
#define INF 0x3f3f3f
int main()
{
    int m;
    scanf("%d",&m);
    for(int i=0;i<m;i++)
        scanf("%d",&a[i]);
    memset(dp,INF,sizeof(dp));
    for(int i=0;i<m;i++)
    {
        *lower_bound(dp,dp+m,a[i])=a[i]; 
    }
    printf("%d\n",lower_bound(dp,dp+m,INF)-dp);
    return 0;
}

//求最长递增公共子序列(时间复杂度为0(n^3))

int dp[maxn][maxn];   //dp[i][j]代表数组 a 前 i 个,数组 b 前 j 个且以 b[j] 为结尾的LCIS
int a[maxn],b[maxn];
int main()
{
    int m,n;
    int i,j;
    scanf("%d %d",&m,&n);
    for(i=1;i<=m;i++)
        scanf("%d",&a[i]);
    for(i=1;i<=n;i++)
        scanf("%d",&b[i]);
    memset(dp,0,sizeof(dp));
    for(i=1;i<=m;i++)
    {
        for(j=1;j<=n;j++)
        {
            if(a[i]!=b[j])
                dp[i][j]=dp[i-1][j];
            else
            {
                for(int k=1;k1][k]+1);
                }
            }
        }
    }
    int ans=0;
    for(i=1;i<=n;i++)
        ans=max(ans,dp[m][i]);
    printf("%d\n",ans);
    return 0;
}

//最长递增公共子序列优化(时间上)

int dp[maxn][maxn];
int a[maxn],b[maxn];
int main()
{
    int m,n;
    int i,j;
    scanf("%d %d",&m,&n);
    for(i=1;i<=m;i++)
        scanf("%d",&a[i]);
    for(i=1;i<=n;i++)
        scanf("%d",&b[i]);
    memset(dp,0,sizeof(dp));
    for(i=1;i<=m;i++)
    {
        int maxx=0;
        for(j=1;j<=n;j++)
        {
            if(a[i]>b[j]) maxx=max(maxx,dp[i-1][j]);   //标记dp[i-1][k]中的最大值
            if(a[i]!=b[j])
                dp[i][j]=dp[i-1][j];
            else
                dp[i][j]=maxx+1;

        }
    }
    int ans=0;
    for(i=1;i<=n;i++)
        ans=max(ans,dp[m][i]);
    printf("%d\n",ans);
    return 0;
}

//最长递增公共子序列优化(空间上)

int dp[maxn];
int a[maxn],b[maxn];
int main()
{
    int m,n;
    int i,j;
    scanf("%d %d",&m,&n);
    for(i=1;i<=m;i++)
        scanf("%d",&a[i]);
    for(i=1;i<=n;i++)
        scanf("%d",&b[i]);
    memset(dp,0,sizeof(dp));
    for(i=1;i<=m;i++)
    {
        int maxx=0;
        for(j=1;j<=n;j++)
        {
            if(a[i]>b[j]) maxx=max(maxx,dp[j]);
            if(a[i]==b[j]) dp[j]=maxx+1;
        }
    }
    int ans=0;
    for(i=1;iprintf("%d\n",ans);
    return 0;
}

你可能感兴趣的:(动规大法,学习总结篇)