3

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

3 Answers3

6

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;
}
rdiachenko
  • 666
  • 9
  • 15
  • it lists all the strings generated in the process of finding all the LCSs. – pranav prashant Sep 08 '15 at 11:47
  • ignore my first statement, the above algorithm is correct!! – pranav prashant Sep 08 '15 at 11:54
  • @rdiachenko : is time complexity for printing out all LCS o(nm) where n being length of the first string and m being length of second? – user1477232 Jan 08 '17 at 09:03
  • 1
    @user1477232, no, in the worst case the time complexity will be about (n + m) * 2^(max(n, m)), where (n + m) is the height of recursive tree and 2^(max(n, m)) is the very approximate number of recursive calls per one level in the recursive tree. You can see the worst case when the input strings consist from completely different characters (e.g.: "abc" and "xyz"). – rdiachenko Jan 08 '17 at 13:04
2

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

}
Charan
  • 971
  • 2
  • 11
  • 27
0

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.

Kundan
  • 51
  • 6