RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1610179
Accepted
gstackoverflow
gstackoverflow
Asked:2025-04-10 15:15:03 +0000 UTC2025-04-10 15:15:03 +0000 UTC 2025-04-10 15:15:03 +0000 UTC

如何解决 Yandex 任务“NOP 带答案恢复”?

  • 772

我正在解决 Yandex 问题并遇到了这个问题:

  1. 带答案恢复的 NOP 平均值给定两个序列,需要找到并输出它们的最大公共子序列。

    让我们提醒您:

    如果 x x 是通过从 𝑦 y 中删除几个(可能是零个或全部)元素得到的,则序列 x x 称为序列 y y 的子序列。

    最长公共子序列是两个序列的子序列中的最长序列。

    输入格式 输入数据的第一行包含数字 N – 第一个序列的长度(1 ≤ N ≤ ≤ 1000)。第二行包含第一个序列的成员(以空格分隔)——绝对值不超过 10,000 的整数。

    第三行包含数字 M – 第二个序列的长度(1 ≤ ≤ M ≤ ≤ 1000)。第四行指定第二个序列的成员(以空格分隔)——绝对值不超过 10,000 的整数。

    输出格式 要求输出给定序列的最大公共子序列,各个序列之间用空格分隔。如果有多个这样的子序列,那么输出其中任何一个都可以。

    注意:在示例2中,有三个最大公共子序列。

    1. 1

    2. 2

    3. 3

    其中任何一个都是正确答案。

在此处输入图片描述

首先我写了一个常规解决方案,它从第一个序列中取出所有子序列(从最长的开始),并将它们与第二个序列中相同长度的子序列进行比较。前几次测试都成功了,但后来我阅读了条件并意识到困难在于可以从序列中任意删除元素。

也就是说,如果给出两个序列:

1 2 3 4 5
1 7 4 3 5

那么答案就是1 4 5

我不知道如何解决这个问题。

алгоритм
  • 2 2 个回答
  • 84 Views

2 个回答

  • Voted
  1. Рустам Рысаев
    2025-04-10T15:27:51Z2025-04-10T15:27:51Z

    有这样一个算法的思路(LCS via DP)让我们有两个序列:

    • A[0...N-1]

    • B[0...M-1]

    创建一个二维数组dp[N+1][M+1],其中:

    • dp[i][j]A[0:i]—和之间的最长公共子序列的长度B[0:j]。

    公式如下:

    if A[i-1] == B[j-1]:
        dp[i][j] = dp[i-1][j-1] + 1
    else:
        dp[i][j] = max(dp[i-1][j], dp[i][j-1])
    

    如果我们讨论完整的代码,我可以举一个例子Python

    def lcs(A, B):
        # Получаем длины последовательностей A и B
        N = len(A)
        M = len(B)
        
        # Создаем двумерный массив dp размером (N+1) x (M+1), и инициализируем его нулями
        # dp[i][j] будет хранить длину наибольшей общей подпоследовательности для первых i элементов A и первых j элементов B
        dp = [[0] * (M + 1) for _ in range(N + 1)]
    
        # Заполняем таблицу dp с использованием динамического программирования
        for i in range(1, N + 1):  # Перебираем элементы последовательности A
            for j in range(1, M + 1):  # Перебираем элементы последовательности B
                if A[i - 1] == B[j - 1]:  # Если текущие элементы равны
                    # Значение dp[i][j] равно dp[i-1][j-1] + 1 (прибавляем этот общий элемент)
                    dp[i][j] = dp[i - 1][j - 1] + 1
                else:
                    # Иначе выбираем максимальную длину из предыдущих вариантов
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
    
        # Восстанавливаем саму наибольшую общую подпоследовательность
        i, j = N, M  # Начинаем с конца таблицы
        result = []  # Список для хранения элементов LCS
    
        while i > 0 and j > 0:  # Пока не достигнем начала таблицы
            if A[i - 1] == B[j - 1]:  # Если элементы на текущих позициях равны
                result.append(A[i - 1])  # Добавляем элемент в результат
                i -= 1  # Переходим к предыдущему элементу в A
                j -= 1  # Переходим к предыдущему элементу в B
            elif dp[i - 1][j] >= dp[i][j - 1]:  # Если длина LCS без элемента B[j-1] больше или равна
                i -= 1  # Переходим к предыдущему элементу в A
            else:  # Если длина LCS без элемента A[i-1] больше
                j -= 1  # Переходим к предыдущему элементу в B
    
        # Поскольку мы восстанавливаем последовательность с конца, нужно перевернуть результат
        return result[::-1]
    
    # Ввод данных
    N = int(input())  # Длина первой последовательности
    A = list(map(int, input().split()))  # Первая последовательность
    M = int(input())  # Длина второй последовательности
    B = list(map(int, input().split()))  # Вторая последовательность
    
    
    print(*lcs(A, B))
    
    
    
    • 2
  2. Best Answer
    Stanislav Volodarskiy
    2025-04-11T18:44:41Z2025-04-11T18:44:41Z

    设s和t为要寻找最长公共子序列的字符串:s由符号s i组成,其中1 ≤ i ≤ m,m是字符串s的长度。t由字符t j组成,其中1 ≤ j ≤ n,n是字符串t的长度。

    符号s [1,i]表示长度为i的字符串s的前缀。类似地,引入t [1,j] ——前缀t。

    s [1,0]和t [1,0]是空字符串。

    给定两个前缀s [1,i]和t [1,j]。我们感兴趣的是最长公共子序列的长度,我们用f i,j表示。

    f的属性是什么?

    1. f i,0 = f 0,j = 0 – 任何字符串与空字符串没有任何共同之处,因此为零。

    2. f i+1,j ≥ f i,j , f i,j+1 ≥ f i,j – 单调性。前缀越长,公共部分越长(而不是更短)。不能通过添加新符号来缩短解决方案。

    3. f i-1,j-1 ≥ f i,j - 1 – f不会增长得太快。如果两个前缀都缩短一个字符,那么只能从整个序列中删除最后一个字符,不能再删除其他字符。

    4. 若s i = t j则f i,j = f i-1,j-1 + 1。如果符号相等,则向最长子序列 ( f i-1,j-1 )加 1 (等于s i和t j 的符号)。由于属性 3,无法添加两个或两个以上。

    5. 如果s i ≠ t j则f i,j = f i-1,j或f i,j = f i,j-1。如果符号不相等,则最长序列不能同时以s i和t j结束。
      如果它不以s i结尾,则f i,j = f i-1,j,因为可以删除符号s i而不会影响解的长度。
      如果它没有在t j处结束,那么f i,j = f i,j-1,因为可以删除符号t j而不会影响解的长度。

    将属性 1、4、5 放在一起,我们得到公式:

    • 如果i = 0或j = 0,则f i, j = 0(属性 1);

    • f i,j = f i-1,j-1 + 1,如果i,j > 0且s i = t j ​​(性质 4);

    • f i,j = max(f i-1,j , f i,j-1 ),如果i, j > 0且s i ≠ t j(属性 5)。

    如果已知f i-1,j、f i,j-1、f i-1,j-1 的值,该公式使我们能够计算f i,j。计算f i,j的时间和内存复杂度都是 O(ij)。如果只需要计算长度,内存复杂度可以降低到O(min(i, j)) 。如果除了长度之外,我们还需要呈现一般序列,那么我们将必须存储f 的所有值。

    子序列从尾到头进行重建。

    我们需要从位置(i, j)移动到位置

    • (i - 1, j - 1),如果i,j > 0且s i = t j ​​;
    • (i - 1, j),如果i, j > 0且s i ≠ t j且f i,j = f i-1,j;
    • (i, j - 1),如果i, j > 0且s i ≠ t j且f i,j = f i,j-1。

    如果i = 0或j = 0,则搜索结束。每当路线上出现等式s i = t j时,相应的符号就会写入答案。最后,答案必须反过来。或者,如果您想避免逆转,请从字符串s和t的末尾开始构建子序列。

    • 1

相关问题

  • Golang 中的堆栈实现

  • 二部图中的最大匹配

  • 求两个数的差模为 m 的倍数的算法

  • 如何将平面几何对象表示为矢量以应用于人工神经网络的输入?[关闭]

  • 如何正确执行矩形的 Delaunay 三角剖分?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5