• 线性dp,优化,272. 最长公共上升子序列


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

    熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目。

    小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们研究最长公共上升子序列了。

    小沐沐说,对于两个数列 A 和 B,如果它们都包含一段位置不一定连续的数,且数值是严格递增的,那么称这一段数是两个数列的公共上升子序列,而所有的公共上升子序列中最长的就是最长公共上升子序列了。

    奶牛半懂不懂,小沐沐要你来告诉奶牛什么是最长公共上升子序列。

    不过,只要告诉奶牛它的长度就可以了。

    数列 A 和 B 的长度均不超过 3000。

    输入格式

    第一行包含一个整数 N,表示数列 A,B 的长度。

    第二行包含 N 个整数,表示数列 A。

    第三行包含 N 个整数,表示数列 B。

    输出格式

    输出一个整数,表示最长公共上升子序列的长度。

    数据范围

    1≤N≤3000,序列中的数字均不超过 231−1。

    输入样例:
    1. 4
    2. 2 2 1 3
    3. 2 1 2 3
    输出样例:
    2

     解析

    (DP,线性DP,前缀和) O(n2)
    这道题目是AcWing 895. 最长上升子序列和AcWing 897. 最长公共子序列的结合版,在状态表示和状态计算上都是融合了这两道题目的方法。

    状态表示:

    f[i][j]代表所有a[1 ~ i]和b[1 ~ j]中以b[j]结尾的公共上升子序列的集合;
    f[i][j]的值等于该集合的子序列中长度的最大值;
    状态计算(对应集合划分):

    首先依据公共子序列中是否包含a[i],将f[i][j]所代表的集合划分成两个不重不漏的子集:

    不包含a[i]的子集,最大值是f[i - 1][j];
    包含a[i]的子集,将这个子集继续划分,依据是子序列的倒数第二个元素在b[]中是哪个数:
    子序列只包含b[j]一个数,长度是1;
    子序列的倒数第二个数是b[1]的集合,最大长度是f[i - 1][1] + 1;

    子序列的倒数第二个数是b[j - 1]的集合,最大长度是f[i - 1][j - 1] + 1;
    如果直接按上述思路实现,需要三重循环:

    作者:yxc
    链接:https://www.acwing.com/solution/content/4955/
    来源:AcWing
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    1. for (int i = 1; i <= n; i ++ )
    2. {
    3. for (int j = 1; j <= n; j ++ )
    4. {
    5. f[i][j] = f[i - 1][j];
    6. if (a[i] == b[j])
    7. {
    8. int maxv = 1;
    9. for (int k = 1; k < j; k ++ )
    10. if (a[i] > b[k])
    11. maxv = max(maxv, f[i - 1][k] + 1);
    12. f[i][j] = max(f[i][j], maxv);
    13. }
    14. }
    15. }
    16. 作者:yxc
    17. 链接:https://www.acwing.com/solution/content/4955/
    18. 来源:AcWing
    19. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

     优化后将三重循环压缩成两成层循环

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. using namespace std;
    15. typedef long long LL;
    16. const int N = 3e3 + 5;
    17. int n;
    18. int a[N], b[N],f[N][N];
    19. int main() {
    20. scanf("%d", &n);
    21. for (int i = 1; i <= n; i++) {
    22. scanf("%d", &a[i]);
    23. }
    24. for (int i = 1; i <= n; i++) {
    25. scanf("%d", &b[i]);
    26. }
    27. for (int i = 1; i <= n; i++) {
    28. int maxv = 1;
    29. for (int j = 1; j <= n; j++) {
    30. f[i][j] = f[i - 1][j];
    31. if (a[i] == b[j]) {
    32. f[i][j] = max(f[i][j], maxv);
    33. }
    34. if (a[i] > b[j])
    35. maxv = max(maxv, f[i - 1][j]+1);
    36. }
    37. }
    38. int ans = 0;
    39. for (int i = 1; i <= n; i++) {
    40. ans = max(ans, f[n][i]);
    41. }
    42. cout << ans << endl;
    43. return 0;
    44. }

  • 相关阅读:
    会议项目之审批
    Double 4 VR智能互动系统在轨道交通实训教学中的应用
    div超出部分省略号显示
    spring bean生命周期
    面试经典150题——Day9
    C盘全面清理教程!彻底清理所有垃圾!
    高性能图表组件LightningChart .NET v11.0发布——增强DPI感知能力
    京东APP技术解密:移动端秒级配置触达平台-Switchquery
    "xxx cannot be cast to jakarta.servlet.Servlet "报错解决方式
    管理 Python 依赖项
  • 原文地址:https://blog.csdn.net/Landing_on_Mars/article/details/132916889