4

我想打印 LCS 问题的所有可能解决方案。

两个字符串 abcbdab 和 bdcaba 应该打印以下 3 个字符串:bdab,bcba,bcab。

C是根据算法取值的全局矩阵表,m,n是序列a,b的长度。

但是输出是出乎意料的。

#include<stdio.h>
#include<conio.h>
int co=0,m=0,n=0,c[10][10];
char a[10],b[10];
void main()
{
    int i,j;
    clrscr();
    printf("Enter Two strings: ");
    scanf("%s",a);
    scanf("%s",b);
    m=strlen(a);
    n=strlen(b);
    for(i=0;i<=m;i++)
    {
        for(j=0;j<=n;j++)
        {   if(i==0 || j==0)
            {
                c[i][j]=0;
            }
            else if(a[i-1]==b[j-1])
            {
                c[i][j]=c[i-1][j-1]+1;
            }
            else if(c[i-1][j]>=c[i][j-1])
            {
                c[i][j]=c[i-1][j];
            }
            else
            {
                c[i][j]=c[i][j-1];
            }
        }
    }
    for(i=0;i<=m;i++)
    {
        for(j=0;j<=n;j++)
        {
            printf("%d\t",c[i][j]);
        }
        printf("\n");
    }
    print(m,n);
    getch();
}
print(int i,int j)
{
    if(i==0 || j==0)
        return 0;
    else if(a[i-1]==b[j-1])
    {
        print(i-1,j-1);
        if(co==c[m][n])
        {
            co=0;
            printf("\n");
        }
        printf("%c",a[i-1]);
        co++;
    }
    else if(c[i-1][j]==c[i][j-1])
    {
        print(i-1,j);
        print(i,j-1);
    }
    else if(c[i][j-1]>=c[i-1][j])
        print(i,j-1);
    else
        print(i-1,j);
    return;
}
4

3 回答 3

6

在这里您可以找到如何执行此操作的递归方法:读出所有 LCS

这是我在 Java 中使用这种方法的代码:

private Set<String> lcs(int[][] dp, String fst, String snd, int i, int j) {
    Set<String> lcss = new HashSet<>();

    if (i == 0 || j == 0) {
        lcss.add("");
    } else if (fst.charAt(i - 1) == snd.charAt(j - 1)) {
        for (String lcs : lcs(dp, fst, snd, i - 1, j - 1)) {
            lcss.add(lcs + fst.charAt(i - 1));
        }
    } else {
        if (dp[i - 1][j] >= dp[i][j - 1]) {
            lcss.addAll(lcs(dp, fst, snd, i - 1, j));
        }

        if (dp[i][j - 1] >= dp[i - 1][j]) {
            lcss.addAll(lcs(dp, fst, snd, i, j - 1));
        }
    }
    return lcss;
}
于 2015-01-23T08:01:10.443 回答
2

这是带有注释的 Java 代码,解释了如何打印所有可能的 lcs。

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class LongestCommonSubsequence {

    public static int[][] LCSmatrix(String X, String Y) {
        //we ignore the top most row and left most column in this matrix
        //so we add 1 and create a matrix with appropriate row and column size 
        int m = X.length() + 1, n = Y.length() + 1;

        int[][] c = new int[m][n];

        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                //since we added 1 to row size and column size,
                // we substract 1 from i,j to find the char at that index
                if (X.charAt(i - 1) == Y.charAt(j - 1)) {
                    c[i][j] = c[i - 1][j - 1] + 1;
                } else if (c[i - 1][j] >= c[i][j - 1]) {
                    c[i][j] = c[i - 1][j];
                } else {
                    c[i][j] = c[i][j - 1];
                }
            }
        }
        printMatrix(c);
        return c;
    }

    public static void printMatrix(int[][] grid) {
        for (int r = 0; r < grid.length; r++) {
            for (int c = 0; c < grid[r].length; c++) {
                System.out.print(grid[r][c] + " ");
            }
            System.out.println();
        }
    }

    public static void allLCS(int[][] c, String X, String Y, int i, int j, Set<String> setLCS, String s) {
        //return when either of the string length is 0
        if (i == 0 || j == 0) {
            setLCS.add(s);
            return;
        }

        //if last characters are equal, they belong in lcs
        if (X.charAt(i - 1) == Y.charAt(j - 1)) {
            //prepend the char to lcs since, we are going backwards
            s = X.charAt(i - 1) + s;
            //continue finding lcs in substrings X.substring(0,i-1) and Y.substring(0,j-1)
            allLCS(c, X, Y, i - 1, j - 1, setLCS, s);
        } // if there is a tie in matrix cells, we backtrack in both ways,
        // else one way, which ever is greater
        else if (c[i - 1][j] == c[i][j - 1]) {
            //continue finding lcs in substring X.substring(0,i-1)
            allLCS(c, X, Y, i - 1, j, setLCS, s);
            //continue finding lcs in substring Y.substring(0,j-1)
            allLCS(c, X, Y, i, j - 1, setLCS, s);
        } else if (c[i - 1][j] > c[i][j - 1]) {
            allLCS(c, X, Y, i - 1, j, setLCS, s);
        } else {
            allLCS(c, X, Y, i, j - 1, setLCS, s);
        }

    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.println(" Enter String X and Y : ");

        String X = sc.next();
        String Y = sc.next();

        sc.close();

        Set<String> set = new HashSet<String>();
        allLCS(LCSmatrix(X, Y), X, Y, X.length(), Y.length(), set, "");

        System.out.println(set.toString());
    }

}
于 2016-10-26T04:20:56.500 回答
-1

您的源代码没有打印 lcs。它实际上是在计算lcs的长度。您提供的源代码完全错误。首先尝试打印一个 lcs。然后扩展该解决方案以打印所有 lcs。为了您的帮助,下面给出了有效的 java 解决方案。

static int arr[][];
static void lcs(String s1, String s2) {
    for (int i = 1; i <= s1.length(); i++) {
        for (int j = 1; j <= s2.length(); j++) {
            if (s1.charAt(i - 1) == s2.charAt(j - 1))
                arr[i][j] = arr[i - 1][j - 1] + 1;
            else
                arr[i][j] = Math.max(arr[i - 1][j], arr[i][j - 1]);
        }
    }
}

static Set<String> lcs(String s1, String s2, int len1, int len2) {
    if (len1 == 0 || len2 == 0) {
        Set<String> set = new HashSet<String>();
        set.add("");
        return set;
    }
    if (s1.charAt(len1 - 1) == s2.charAt(len2 - 1)) {
        Set<String> set = lcs(s1, s2, len1 - 1, len2 - 1);
        Set<String> set1 = new HashSet<>();
        for (String temp : set) {
            temp = temp + s1.charAt(len1 - 1);
            set1.add(temp);
        }
        return set1;
    } else {
        Set<String> set = new HashSet<>();
        Set<String> set1 = new HashSet<>();
        if (arr[len1 - 1][len2] >= arr[len1][len2 - 1]) {
            set = lcs(s1, s2, len1 - 1, len2);
        }
        if (arr[len1][len2 - 1] >= arr[len1 - 1][len2]) {
            set1 = lcs(s1, s2, len1, len2 - 1);
        }
        for (String temp : set) {
            set1.add(temp);
        }
        //System.out.println("In lcs" + set1);
        return set1;

    }
}


public static void main(String[] args) {
    String s1 = "abcbdab";
    String s2 = "bdcaba ";
    arr = new int[s1.length() + 1][s2.length() + 1];
    lcs(s1, s2);
    System.out.println(lcs(s1, s2, s1.length(), s2.length()));
}

如果字符串的最后一个字符相等,则它们必须在 lcs 中。如果它们不相等,则 lcs 将从矩阵的上侧或矩阵的左侧构造,具体取决于哪个值更大。如果两个值相等,则 lcs 将从两侧构造。因此,请继续构建 lcs,直到您构建完所有 lcs 并将它们存储在一个集合中。

于 2014-11-03T16:00:45.680 回答