How to print all possible solutions for Longest Common subsequence

谁说胖子不能爱 提交于 2019-12-12 14:03:53

问题


I want to print all the possible solutions to LCS problem.

The two strings abcbdab and bdcaba should print following 3 strings: bdab,bcba,bcab.

C is the global matrix table which takes values according to algorithm and m, n are the length of the sequences a, b.

But The output is something unexpected.

#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;
}

回答1:


Here you can find a recursive approach of how to do this: Reading out all LCSs

Here is my code for this approach in 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;
}



回答2:


Your source code is not printing the lcs. It is actually calculating the length of lcs. Source code given by you is totally wrong. First try to print one lcs. Then extend that solution to print all the lcs. For your help given below is working java solution.

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()));
}

If last character of strings are equal then they must be in lcs. If they are not equal lcs will be either constructed from upper side of matrix or left side of matrix depending upon which value is greater. If both the value is equal then lcs will be constructed from both the side. So keep constructing the lcs until you have constructed all the lcs and store them in a set.




回答3:


Here is the Java code with comments explaining how to print all possible 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());
    }

}


来源:https://stackoverflow.com/questions/22299345/how-to-print-all-possible-solutions-for-longest-common-subsequence

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!