当前位置: 首页 > 知识库问答 >
问题:

Go:打印结果数组的最长公共子序列

戚令秋
2023-03-14

我已经实现了最长公共子序列算法,并获得了最长的正确答案,但无法找出打印出组成最长公共子序列的方法。

也就是说,我成功地获得了最长公共子序列数组的长度,但我想打印出最长的子序列。

这个代码的操场在这里

http://play.golang.org/p/0sKb_OARnf

/*
X = BDCABA
Y = ABCBDAB => Longest Comman Subsequence is B C B

Dynamic Programming method : O ( n )
*/

package main
import "fmt"

func Max(more ...int) int {
  max_num := more[0]
  for _, elem := range more {
    if max_num < elem {
      max_num = elem
    }
  }
  return max_num
}

func Longest(str1, str2 string) int {
  len1 := len(str1)
  len2 := len(str2)

  //in C++,
  //int tab[m + 1][n + 1];
  //tab := make([][100]int, len1+1)

  tab := make([][]int, len1+1)
  for i := range tab {
    tab[i] = make([]int, len2+1)
  }

  i, j := 0, 0
  for i = 0; i <= len1; i++ {
    for j = 0; j <= len2; j++ {
      if i == 0 || j == 0 {
        tab[i][j] = 0
      } else if str1[i-1] == str2[j-1] {
        tab[i][j] = tab[i-1][j-1] + 1
        if i < len1 {
          fmt.Printf("%c", str1[i])
        }
      } else {
        tab[i][j] = Max(tab[i-1][j], tab[i][j-1])
      }
    }
  }
  fmt.Println()
  return tab[len1][len2]
}

func main() {
  str1 := "AGGTABTABTABTAB"
  str2 := "GXTXAYBTABTABTAB"
  fmt.Println(Longest(str1, str2))
  //Actual Longest Common Subsequence: GTABTABTABTAB
  //GGGGGTAAAABBBBTTTTAAAABBBBTTTTAAAABBBBTTTTAAAABBBB
  //13

  str3 := "AGGTABGHSRCBYJSVDWFVDVSBCBVDWFDWVV"
  str4 := "GXTXAYBRGDVCBDVCCXVXCWQRVCBDJXCVQSQQ"
  fmt.Println(Longest(str3, str4))
  //Actual Longest Common Subsequence: ?
  //GGGTTABGGGHHRCCBBBBBBYYYJSVDDDDDWWWFDDDDDVVVSSSSSBCCCBBBBBBVVVDDDDDWWWFWWWVVVVVV
  //14
}

当我尝试在标签得到更新时打印出子序列时,结果是重复的。我想为str1和str2打印出类似“GTABTABTABTAB”的东西

提前谢谢。

共有1个答案

荆修明
2023-03-14

编辑:看来我在回答这个问题时太过火了。在Wikipedia页面上,他们给出了最长公共子序列的伪代码,用于在计算完LCS后打印出LCS。我一有时间就会把它的实现放到这里。

一旦将角色注册为子序列的一部分,您就会忘记从该角色开始移动。

下面的代码应该有效。看一下fmt后面的两行。Printf(“%c”,srt1[i])行。

操场链接

/*
X = BDCABA
Y = ABCBDAB => Longest Comman Subsequence is B C B

Dynamic Programming method : O ( n )
*/

package main

import "fmt"

func Max(more ...int) int {
    max_num := more[0]
     for _, elem := range more {
        if max_num < elem {
            max_num = elem
        }
    }
    return max_num
}

func Longest(str1, str2 string) int {
    len1 := len(str1)
    len2 := len(str2)

    //in C++,
    //int tab[m + 1][n + 1];
    //tab := make([][100]int, len1+1)

    tab := make([][]int, len1+1)
    for i := range tab {
        tab[i] = make([]int, len2+1)
    }

    i, j := 0, 0
    for i = 0; i <= len1; i++ {
        for j = 0; j <= len2; j++ {
            if i == 0 || j == 0 {
                tab[i][j] = 0
            } else if str1[i-1] == str2[j-1] {
                tab[i][j] = tab[i-1][j-1] + 1
                if i < len1 {
                    fmt.Printf("%c", str1[i])
                                            //Move on the the next character in both sequences
                    i++
                    j++
                }
            } else {
                tab[i][j] = Max(tab[i-1][j], tab[i][j-1])
            }
        }
    }
    fmt.Println()
    return tab[len1][len2]
}

func main() {
    str1 := "AGGTABTABTABTAB"
    str2 := "GXTXAYBTABTABTAB"
    fmt.Println(Longest(str1, str2))
    //Actual Longest Common Subsequence: GTABTABTABTAB
    //GGGGGTAAAABBBBTTTTAAAABBBBTTTTAAAABBBBTTTTAAAABBBB
    //13

    str3 := "AGGTABGHSRCBYJSVDWFVDVSBCBVDWFDWVV"
    str4 := "GXTXAYBRGDVCBDVCCXVXCWQRVCBDJXCVQSQQ"
    fmt.Println(Longest(str3, str4))
    //Actual Longest Common Subsequence: ?
     //GGGTTABGGGHHRCCBBBBBBYYYJSVDDDDDWWWFDDDDDVVVSSSSSBCCCBBBBBBVVVDDDDDWWWFWWWVVVVVV
    //14
}
 类似资料:
  • longestCommonSubsequence正在返回LCS的长度。代码运行良好。但我试图打印子序列的值。例如,它应该打印“acef”。但我的代码只打印“ae”<如何修复? 这是完整的代码https://pastebin.com/Sq4QMtxF

  • 几个小时以来,我一直在尝试实现最长的公共子序列。我已经检查了LCSLength函数是否返回正确的长度,但它没有正确打印序列。 我下面给出的伪代码:http://en.wikipedia.org/wiki/Longest_common_subsequence_problem 如果您能提供任何帮助,我们将不胜感激。 测试案例: 返回4但字符串序列不正确。 返回14 谢谢

  • 我试图在c中实现最长公共子序列算法,矩阵c[]]存储最长公共子序列的长度,行[][]存储c[]]矩阵中的父块行,列[][]存储父块列。 我对解决LCS的方法非常不便和低效表示歉意,但什么都没有打印出来。请帮忙。

  • Iam尝试使用以下代码打印所有可能的最长公共子序列 1-首先,我找到了LCS长度dp矩阵,并尝试使用递归生成所有可能的输出。 输入和输出 实际上,每次我将字符添加到输出列表时,我都需要弹出字符并将其插入为旧的附加新的。但是当我添加行时 然后它只显示了LCS的一种可能性,而不是全部。请帮助,我哪里出错了?

  • 然而,我意识到我真正想解决的问题有点不同。给定一个固定的k,我需要确保公共子序列只涉及长度正好为k的子串。例如,设置k=2,并让这两个字符串为 我需要的子序列是“。 是否可以修改动态规划解来解决这个问题?

  • 我目前正在尝试为2个给定字符串查找和打印最长的公共子序列。我使用最常见的算法,没有递归。如果我保留整个数组,这是一项简单的任务,但我正在尝试对其进行一点优化,只使用2行,您可以在下面的代码中看到。有了这个更改,查找长度仍然很简单,工作正常,但恢复子序列不再那么容易了。我尝试了几种方法,但都不起作用。下面你可以看到我最后的尝试。虽然它适用于相同的情况,但也有失败的情况。经过长时间的思考,我开始相信没