AcWing 272. 最长公共上升子序列

举报
辰chen 发表于 2022/06/15 00:51:51 2022/06/15
【摘要】 AcWing 272. 最长公共上升子序列 AcWing 272. 最长公共上升子序列AC代码 AcWing 272. 最长公共上升子序列 本题链接:AcWing 272. 最长公共上...

AcWing 272. 最长公共上升子序列


AcWing 272. 最长公共上升子序列

本题链接:AcWing 272. 最长公共上升子序列

本博客给出本题截图
在这里插入图片描述

AC代码

代码解释f[i][j]代表所有在a[1 ~n]b[1 ~ n]中都出现过,并且以b[j]结尾的公共上升子序列的最大值的集合
如果不包含a[i]的话那么

f[i][j] = f[i - 1][j];

  
 

如果包含a[i]的话,那么我们现在的公共上升子序列必然最后一位是a[i] (b[j]),那么我们开始根据倒数第二位去继续划分,进行状态转移,那么我们假设这个子序列的倒数第二位是b[k] (k < j),当k == 0时证明没有倒数第二位,即当前子序列只有一个数,即maxv = 1,然后k1 开始遍历到 j - 1,注意在遍历的过程中,只有满足 b[k] < b[j]才可以更新maxv

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

  
 

TLE版

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 3010;

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

int main()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i ++ ) cin >> a[i];
    for (int i = 1; i <= n; i ++ ) cin >> b[i];

    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 (b[k] < b[j]) 
                        maxv = max(maxv, f[i - 1][k] + 1);
                f[i][j] = max(f[i][j], maxv);
            }
        }

    int res = 0;
    for (int i = 1; i <= n; i ++ ) res = max(res, f[n][i]);
    cout << res << endl;

    return 0;
}

  
 

代码优化:三重循环,TLE 也不太意外,如何去优化呢?从第三重循环去下手,我们发现,对于我们遍历的每一个j,第三重循环都会重新遍历一遍1 ~ j - 1,这样显然是有很多重复在其中的,我们如果可以每次都把1 ~ j - 1中的最大值给存储起来,那么当我们j ++后,下一次该遍历1 ~ j的时候,只需要用这个最大值再去和j去比较即可,故我们把maxv放到一重循环中,然后来观察那个TLE代码:

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

  
 

在这个代码中if (b[k] < b[j])可以替换为if (b[k] < a[i]),因为大前提是if (a[i] == b[j]),那么这个第三重的for循环就可以理解成在前j - 1中找到所有b[k] < a[i]的然后去更新,故当我们去掉第三重循环后可优化为:

if (a[i] > b[j]) maxv = max(maxv, f[i - 1][j] + 1);

  
 

AC代码

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 3010;

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

int main()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i ++ ) cin >> a[i];
    for (int i = 1; i <= n; i ++ ) cin >> 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]);
    cout << res << endl;

    return 0;
}

  
 

文章来源: chen-ac.blog.csdn.net,作者:辰chen,版权归原作者所有,如需转载,请联系作者。

原文链接:chen-ac.blog.csdn.net/article/details/119893807

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。