Print all possible ways to convert one string into another string | Edit-Distance

Prerequisite: Dynamic Programming | Set 5 (Edit Distance) 
Given two strings str1 and str2, the task is to print the all possible ways to convert ‘str1’ into ‘str2’. 
Below are the operations that can be performed on “str1”: 
 
- Insert
- Remove
- Replace
All of the above operations are of equal cost. The task is to print all the various ways to convert ‘str1’ into ‘str2’ using the minimum number of edits (operations) required, where a “way” comprises of the series of all such operations required. 
Examples: 
 
Input: str1 = “abcdef”, str2 = “axcdfdh”
Output:
Method 1:
Add h
Change f to d
Change e to f
Change b to x
Method 2:
Change f to h
Add d
Change e to f
Change b to x
Method 3:
Change f to h
Change e to d
Add f
Change b to x
Approach for printing one possible way:
The approach for finding the minimum number of edits has been discussed in this post. To print one possible way, iterate from the bottom right corner of the DP matrix formed using Min-Edit Distance method. Check if the character pertaining to that element in both strings is equal or not. If it is, it means it needs no edit, and DP[i][j] was copied from DP[i-1][j-1]. 
 
If str1[i-1] == str2[j-1], proceed diagonally.
Note that since the DP matrix contains one extra row and column at 0 indices, String indexes will be decreased by one. i.e. DP[i][j] corresponds to i-1 index of str1 and j-1 index of str2.
Now, if the characters were not equal, that means this matrix element DP[i][j] was obtained from the minimum of DP[i-1][j-1], DP[i][j-1] and DP[i-1][j], plus 1. Hence, check from where this element was from. 
 
1. If DP[i][j] == DP[i-1][j-1] + 1
It means the character was replaced from str1[i] to str2[j]. Proceed diagonally.
2. If DP[i][j] == DP[i][j-1] + 1
It means the character was Added from str2[j]. Proceed left.
3. If DP[i][j] == DP[i-1][j] + 1
It means the character str1[i] was deleted. Proceed up.
Once the end i.e., (i==0 and j==0 ) of both strings is reached, converting of one string to other is done. We will have printed all the set of operations required. 
Below is the implementation of the above approach: 
 
C++
| // C++ program to print one possible// way of converting a string to another#include <bits/stdc++.h>usingnamespacestd;intDP[100][100];// Function to print the stepsvoidprintChanges(string s1, string s2,                          intdp[][100]){    inti = s1.length();    intj = s2.length();    // check till the end    while(i and j)    {        // if characters are same        if(s1[i - 1] == s2[j - 1])        {            i--;            j--;        }        // Replace        elseif(dp[i][j] == dp[i - 1][j - 1] + 1)        {            cout << "change "<< s1[i - 1]                  << " to "<< s2[j - 1] << endl;            i--;            j--;        }        // Delete the character        elseif(dp[i][j] == dp[i - 1][j] + 1)        {            cout << "Delete "<< s1[i - 1] << endl;            i--;        }        // Add the character        elseif(dp[i][j] == dp[i][j - 1] + 1)        {            cout << "Add "<< s2[j - 1] << endl;            j--;        }    }}// Function to compute the DP matrixvoideditDP(string s1, string s2){    intl1 = s1.length();    intl2 = s2.length();    DP[l1 + 1][l2 + 1];    // initialize by the maximum edits possible    for(inti = 0; i <= l1; i++)        DP[i][0] = i;    for(intj = 0; j <= l2; j++)        DP[0][j] = j;    // Compute the DP matrix    for(inti = 1; i <= l1; i++)    {        for(intj = 1; j <= l2; j++)        {            // if the characters are same            // no changes required            if(s1[i - 1] == s2[j - 1])                DP[i][j] = DP[i - 1][j - 1];            else                // minimum of three operations possible                DP[i][j] = min(min(DP[i - 1][j - 1],                                    DP[i - 1][j]),                                   DP[i][j - 1]) + 1;        }    }    // print the steps    printChanges(s1, s2, DP);}// Driver Codeintmain(){    string s1 = "abcdef";    string s2 = "axcdfdh";    // calculate the DP matrix    editDP(s1, s2);    return0;}// This code is contributed by// sanjeev2552 | 
Java
| importjava.util.*;classFollowUp_PrintOneWayToConvert {    publicstaticvoidmain(String[] args) {        var o = newFollowUp_PrintOneWayToConvert();        o.minDistance("abcdef", "axcdfdh");        for(var r : o.dp) System.out.println(Arrays.toString(r));        o.printChanges("abcdef", "axcdfdh");        // Only add: GeeksForGeeks impl won't print added chars        o = newFollowUp_PrintOneWayToConvert();        o.minDistance("", "abc");        for(var r : o.dp) System.out.println(Arrays.toString(r));        o.printChanges("", "abc");        // Only remove: GeeksForGeeks impl won't print removed chars        o = newFollowUp_PrintOneWayToConvert();        o.minDistance("abc", "");        for(var r : o.dp) System.out.println(Arrays.toString(r));        o.printChanges("abc", "");    }    int[][] dp;    intminDistance(String s, String targ) {        intm = s.length(), n = targ.length();        dp = newint[m + 1][n + 1];        // initialize by the maximum edits possible        for(inti = 0; i <= m; i++) dp[i][0] = i;        for(intj = 0; j <= n; j++) dp[0][j] = j;        for(inti = 1; i <= m; i++)            for(intj = 1; j <= n; j++)                if(s.charAt(i - 1) == targ.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1];                elsedp[i][j] = 1+ Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1]));        returndp[m][n];    }    voidprintChanges(String s, String t) {        inti = s.length(), j = t.length();        while(i > 0&& j > 0) {            // Match(if characters same):            if(s.charAt(i - 1) == t.charAt(j - 1)) { i--; j--; }            // No match:            // Replace            elseif(dp[i][j] == dp[i - 1][j - 1] + 1) { System.out.println("Change "+ s.charAt(i - 1) + " to "+ t.charAt(j - 1)); i--; j--; }            // Delete the character            elseif(dp[i][j] == dp[i - 1][j] + 1) { System.out.println("Delete "+ s.charAt(i - 1)); i--; }            // Add character            elseif(dp[i][j] == dp[i][j - 1] + 1) { System.out.println("Add "+ t.charAt(j - 1)); j--; }        } // i or j == 0, so we need to only remove or add chars        while(i > 0) System.out.println("Delete "+ s.charAt(--i)); // 't' matched but some 's' chars left not removed - rm all 's' chars        while(j > 0) System.out.println("Add "+ t.charAt(--j)); // 's' chars finished but not all 't' chars matched - add missing    }} | 
Python3
| # Python3 program to print one possible # way of converting a string to another # Function to print the stepsdefprintChanges(s1, s2, dp):        i =len(s1)    j =len(s2)       # Check till the end     while(i > 0andj > 0):                # If characters are same         ifs1[i -1] ==s2[j -1]:            i -=1            j -=1                    # Replace        elifdp[i][j] ==dp[i -1][j -1] +1:            print("change", s1[i -1],                      "to", s2[j -1])            j -=1            i -=1                    # Delete        elifdp[i][j] ==dp[i -1][j] +1:            print("Delete", s1[i -1])            i -=1                    # Add        elifdp[i][j] ==dp[i][j -1] +1:            print("Add", s2[j -1])            j -=1            # Function to compute the DP matrix defeditDP(s1, s2):        len1 =len(s1)    len2 =len(s2)    dp =[[0fori inrange(len2 +1)]             forj inrange(len1 +1)]        # Initialize by the maximum edits possible     fori inrange(len1 +1):        dp[i][0] =i    forj inrange(len2 +1):        dp[0][j] =j        # Compute the DP Matrix    fori inrange(1, len1 +1):        forj inrange(1, len2 +1):                        # If the characters are same             # no changes required             ifs2[j -1] ==s1[i -1]:                dp[i][j] =dp[i -1][j -1]                            # Minimum of three operations possible             else:                dp[i][j] =1+min(dp[i][j -1],                                   dp[i -1][j -1],                                   dp[i -1][j])                                       # Print the steps     printChanges(s1, s2, dp)# Driver Code s1 ="abcdef"s2 ="axcdfdh"# Compute the DP MatrixeditDP(s1, s2)# This code is contributed by Pranav S | 
C#
| // C# program to print one possible// way of converting a string to anotherusingSystem;publicclassGFG{    staticint[,]dp;    // Function to print the steps    staticvoidprintChanges(String s1, String s2)    {        inti = s1.Length;        intj = s2.Length;        // check till the end        while(i != 0 && j != 0)         {            // if characters are same            if(s1[i - 1] == s2[j - 1])             {                i--;                j--;            }            // Replace            elseif(dp[i, j] == dp[i - 1, j - 1] + 1)            {                Console.WriteLine("change "+ s1[i - 1] + " to "+ s2[j - 1]);                i--;                j--;            }            // Delete the character            elseif(dp[i, j] == dp[i - 1, j] + 1)            {                Console.WriteLine("Delete "+ s1[i - 1]);                i--;            }            // Add the character            elseif(dp[i, j] == dp[i, j - 1] + 1)            {                Console.WriteLine("Add "+ s2[j - 1]);                j--;            }        }    }    // Function to compute the DP matrix    staticvoideditDP(String s1, String s2)    {        intl1 = s1.Length;        intl2 = s2.Length;        int[,] DP = newint[l1 + 1, l2 + 1];        // initialize by the maximum edits possible        for(inti = 0; i <= l1; i++)            DP[i, 0] = i;        for(intj = 0; j <= l2; j++)            DP[0, j] = j;        // Compute the DP matrix        for(inti = 1; i <= l1; i++)        {            for(intj = 1; j <= l2; j++)            {                // if the characters are same                // no changes required                if(s1[i - 1] == s2[j - 1])                    DP[i, j] = DP[i - 1, j - 1];                else                {                    // minimum of three operations possible                    DP[i, j] = min(DP[i - 1, j - 1],                                DP[i - 1, j], DP[i, j - 1])                            + 1;                }            }        }        // initialize to global array        dp = DP;    }    // Function to find the minimum of three    staticintmin(inta, intb, intc)    {        intz = Math.Min(a, b);        returnMath.Min(z, c);    }    // Driver Code    publicstaticvoidMain(String[] args)    {        String s1 = "abcdef";        String s2 = "axcdfdh";        // calculate the DP matrix        editDP(s1, s2);        // print the steps        printChanges(s1, s2);    }}// This code is contributed by PrinciRaj1992 | 
Javascript
| // Javascript code for the above approachlet DP = Array(100).fill().map(() => Array(100).fill(0));functionprintChanges(s1, s2, dp) {    let i = s1.length;    let j = s2.length;    // check till the end    while(i && j) {        // if characters are same        if(s1[i - 1] === s2[j - 1]) {            i--;            j--;        }        // Replace        elseif(dp[i][j] === dp[i - 1][j - 1] + 1) {            console.log(`change ${s1[i - 1]} to ${s2[j - 1]<br>}`);            i--;            j--;        }        // Delete the character        elseif(dp[i][j] === dp[i - 1][j] + 1) {            console.log(`Delete ${s1[i - 1]}<br>`);            i--;        }        // Add the character        elseif(dp[i][j] === dp[i][j - 1] + 1) {            console.log(`Add ${s2[j - 1]}<br>`);            j--;        }    }}functioneditDP(s1, s2) {    let l1 = s1.length;    let l2 = s2.length;    // initialize by the maximum edits possible    for(let i = 0; i <= l1; i++) {        DP[i][0] = i;    }    for(let j = 0; j <= l2; j++) {        DP[0][j] = j;    }    // Compute the DP matrix    for(let i = 1; i <= l1; i++) {        for(let j = 1; j <= l2; j++) {            // if the characters are same            // no changes required            if(s1[i - 1] === s2[j - 1]) {                DP[i][j] = DP[i - 1][j - 1];            } else{                // minimum of three operations possible                DP[i][j] = Math.min(Math.min(DP[i - 1][j - 1], DP[i - 1][j]), DP[i][j - 1]) + 1;            }        }    }    // print the steps    printChanges(s1, s2, DP);}// Driver Codelet s1 = "abcdef";let s2 = "axcdfdh";// calculate the DP matrixeditDP(s1, s2);// This code is contributed by lokeshpotta20. | 
change f to h change e to d Add f change b to x
The time complexity of the given implementation of the edit distance algorithm is O(m*n), where m and n are the lengths of the input strings s1 and s2, respectively. This is because the DP matrix is computed in a nested loop that iterates over each position in the matrix exactly once.
The space complexity of the implementation is O(m*n) as well, since the DP matrix is stored in a two-dimensional array of size (m+1) x (n+1). This is because the algorithm needs to store the minimum edit distance values for each prefix of s1 and s2, including the empty string prefixes.
 
Approach to print all possible ways:
Create a collection of strings that will store the operations required. This collection can be a vector of strings in C++ or a List of strings in Java. Add operations just like printing them before to this collection. Then create a collection of these collections which will store the multiple methods (sets of string operations). 
Else-if was used earlier to check from where we derived the DP[i][j] from. Now, check all If’s to see if there were more than 1 ways you could obtain the element. If there was, we create a new collection from before, remove the last operation, add this new operation and initiate another instance of this function with this new list. In this manner, add new lists whenever there was a new method to change str1 to str2, getting a new method every time.
On reaching the end of either string, add this list to the collection of lists, thus completing the set of all possible operations, and add them. 
Below is the implementation of the above approach: 
 
C++
| usingSystem;usingSystem.Collections.Generic;classProgram{    // Create List of lists that will store all sets of operations    staticList<List<string>> arrs = newList<List<string>>();    staticint[,] dp = newint[1001, 1001];    // Function to print all ways    staticvoidPrintAllChanges(string s1, string s2, List<string> changes)    {        inti = s1.Length;        intj = s2.Length;        // Iterate till the end        while(true)        {            if(i == 0 || j == 0)            {                // Add this list to our List of lists.                arrs.Add(newList<string>(changes));                break;            }            // If same            if(s1[i - 1] == s2[j - 1])            {                i--;                j--;            }            else            {                boolif1 = false, if2 = false;                // Replace                if(dp[i, j] == dp[i - 1, j - 1] + 1)                {                    // Add this step                    changes.Add("Change "+ s1[i - 1] + " to "+ s2[j - 1]);                    i--;                    j--;                    if1 = true;                }                // Delete                if(dp[i, j] == dp[i - 1, j] + 1)                {                    if(!if1)                    {                        changes.Add("Delete "+ s1[i - 1]);                        i--;                    }                    else                    {                        // If the previous method was true,                        // create a new list as a copy of the previous.                        List<string> changes2 = newList<string>(changes);                        changes2.RemoveAt(changes2.Count - 1);                        // Add this new operation                        changes2.Add("Delete "+ s1[i]);                        // Initiate a new instance of this function with remaining substrings                        PrintAllChanges(s1.Substring(0, i), s2.Substring(0, j + 1), changes2);                    }                    if2 = true;                }                // Add character step                if(dp[i, j] == dp[i, j - 1] + 1)                {                    if(!if1 && !if2)                    {                        changes.Add("Add "+ s2[j - 1]);                        j--;                    }                    else                    {                        // Add steps                        List<string> changes2 = newList<string>(changes);                        changes2.RemoveAt(changes2.Count - 1);                        changes2.Add("Add "+ s2[j]);                        // Recursively call for the next steps                        PrintAllChanges(s1.Substring(0, i + 1), s2.Substring(0, j), changes2);                    }                }            }        }    }    // Function to compute the DP matrix    staticvoidEditDP(string s1, string s2)    {        intl1 = s1.Length;        intl2 = s2.Length;        // Initialize by the maximum edits possible        for(inti = 0; i <= l1; i++)            dp[i, 0] = i;        for(intj = 0; j <= l2; j++)            dp[0, j] = j;        // Compute the DP matrix        for(inti = 1; i <= l1; i++)        {            for(intj = 1; j <= l2; j++)            {                // If the characters are the same, no changes required                if(s1[i - 1] == s2[j - 1])                    dp[i, j] = dp[i - 1, j - 1];                else                    // Minimum of three operations possible                    dp[i, j] = Math.Min(dp[i - 1, j - 1], Math.Min(dp[i - 1, j], dp[i, j - 1])) + 1;            }        }    }    staticvoidPrintWays(string s1, string s2, List<string> changes)    {        // Function to print all the ways        PrintAllChanges(s1, s2, newList<string>());        inti = 1;        // Print all the possible ways        foreach (var ar in arrs)        {            Console.WriteLine("\nMethod "+ i + " : ");            foreach (var s in ar)            {                Console.WriteLine(s);            }            i++;        }    }    // Driver Code    staticvoidMain()    {        string s1 = "abcdef";        string s2 = "axcdfdh";        // Calculate the DP matrix        EditDP(s1, s2);        // Function to print all ways        PrintWays(s1, s2, newList<string>());    }} | 
Java
| importjava.util.*;classFollowUp_PrintAllPossibleChanges {    int[][] dp;    // List of changes stores all possible ways, each way - list of operations    List<List<String> > allWays = newArrayList<>();    intminDistance(String s, String targ) {        intm = s.length(), n = targ.length();        dp = newint[m + 1][n + 1];        // initialize by the maximum edits possible        for(inti = 0; i <= m; i++) dp[i][0] = i;        for(intj = 0; j <= n; j++) dp[0][j] = j;        for(inti = 1; i <= m; i++)            for(intj = 1; j <= n; j++)                if(s.charAt(i - 1) == targ.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1];                elsedp[i][j] = 1+ Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1]));        returndp[m][n];    }    voidprintAllChanges(String s, String t, List<String> changes) {        inti = s.length(), j = t.length();        while(i > 0&& j > 0) {            if(s.charAt(i - 1) == t.charAt(j - 1)) { i--; j--; } // Match            else{ // Not match:                booleanreplaced = false, deleted = false;                intnextI = i, nextJ = j; // We dont want 1st if influence other ifs                // Don't just pick single way, try all 3 ways if they all minimal                if(dp[i][j] == dp[i - 1][j - 1] + 1) { // Replace                    changes.add(s.charAt(i - 1) + "->"+ t.charAt(j - 1));                    nextI = i - 1; nextJ = j - 1; replaced = true;                }                if(dp[i][j] == dp[i - 1][j] + 1) { // Delete                    if(!replaced) { changes.add("Del "+ s.charAt(i - 1)); nextI = i - 1; } // Reuse 'changes' if only single operation possible                    else{                        // If also was replaced -> we have at least 2 ways for edit,                        // so create new changes(like new path) & remove 'Replace' operation coz here we chosen to 'Delete'                        // (Changes should have one of 3 operations, can't replace and remove same char, that doesnt make sense)                        var changes2 = newArrayList<>(changes);                        changes2.remove(changes.size() - 1); // Remove last operation                        changes2.add("Del "+ s.charAt(i - 1)); // Add this new operation                        // initiate new instance of this fun with remaining substrings                        printAllChanges(s.substring(0, i - 1), t.substring(0, j), changes2);                    }                    deleted = true;                }                if(dp[i][j] == dp[i][j - 1] + 1) { // Add ch                    if(!replaced && !deleted) { changes.add("Add "+ t.charAt(j - 1)); nextJ = j - 1; } // One op only if not Replaced & Deleted                    else{                        var changes2 = newArrayList<>(changes);                        changes2.remove(changes.size() - 1);                        changes2.add("Add "+ t.charAt(j - 1));                        printAllChanges(s.substring(0, i), t.substring(0, j - 1), changes2);                    }                }                i = nextI; j = nextJ;            }        }        while(i > 0) changes.add("Del "+ s.charAt(--i)); // 't' matched but some 's' chars left not removed - rm all 's' chars        while(j > 0) changes.add("Add "+ t.charAt(--j)); // 's' chars finished but not all 't' chars matched - add missing        allWays.add(changes);    }    voidprintWays(String s1, String s2) {        printAllChanges(s1, s2, newArrayList<>());        inti = 1;        for(var way : allWays) {            System.out.print("Method #"+ i++ + ": ");            System.out.println(String.join(", ", way));        }    }    publicstaticvoidmain(String[] args) throwsException {        var o = newFollowUp_PrintAllPossibleChanges();        o.minDistance("abcdef", "axcdfdh");        o.printWays("abcdef", "axcdfdh");        // Only add: GeeksForGeeks impl won't print added chars        o = newFollowUp_PrintAllPossibleChanges();        o.minDistance("", "abc");        o.printWays("", "abc");        // Only remove: GeeksForGeeks impl won't print removed chars        o = newFollowUp_PrintAllPossibleChanges();        o.minDistance("abc", "");        o.printWays("abc", "");    }} | 
Python3
| importnumpy as np# create List of lists that will store all sets of operationsarrs =[]# Function to print all waysdefprintAllChanges(s1, s2, changes):    i =len(s1)    j =len(s2)    # Iterate till end    whileTrue:        ifi ==0orj ==0:            # Add this list to our List of lists.            arrs.append(changes)            break        # If same        ifs1[i -1] ==s2[j -1]:            i -=1            j -=1        else:            if1 =False            if2 =False            # Replace            ifdp[i][j] ==dp[i -1][j -1] +1:                # Add this step                changes.append(f"Change {s1[i-1]} to {s2[j-1]}")                i -=1                j -=1                if1 =True            # Delete            ifdp[i][j] ==dp[i -1][j] +1:                ifnotif1:                    changes.append(f"Delete {s1[i-1]}")                    i -=1                else:                    # If the previous method was true,                    # create a new list as a copy of previous.                    changes2 =changes.copy()                    changes2.pop()                    # Add this new operation                    changes2.append(f"Delete {s1[i]}")                    # initiate new new instance of this function with remaining substrings                    printAllChanges(s1[:i], s2[:j +1], changes2)                if2 =True            # Add character step            ifdp[i][j] ==dp[i][j -1] +1:                ifnotif1 andnotif2:                    changes.append(f"Add {s2[j-1]}")                    j -=1                else:                    # Add steps                    changes2 =changes.copy()                    changes2.pop()                    changes2.append(f"Add {s2[j]}")                    # Recursively call for the next steps                    printAllChanges(s1[:i +1], s2[:j], changes2)            # Move to previous subproblem            i -=1            j -=1# Function to compute the DP matrixdefeditDP(s1, s2):    l1 =len(s1)    l2 =len(s2)    # initialize by the maximum edits possible    dp =np.zeros((l1+1, l2+1))    fori inrange(l1+1):        dp[i][0] =i    forj inrange(l2+1):        dp[0][j] =j    # Compute the DP matrix    fori inrange(1, l1+1):        forj inrange(1, l2+1):            # if the characters are same            # no changes required            ifs1[i -1] ==s2[j -1]:                dp[i][j] =dp[i -1][j -1]            else:                # minimum of three operations possible                dp[i][j] =min(dp[i -1][j -1], dp[i -1][j], dp[i][j -1]) +1    returndpdefprintWays(s1, s2, changes):    # Function to print all the ways    printAllChanges(s1, s2, [])    i =1    # print all the possible ways    forar inarrs:        print("\nMethod {}: ".format(i))        fors inar:            print(s)        i +=1# Driver Codeif__name__ =="__main__":    s1 ="abcdef"    s2 ="axcdfdh"    # calculate the DP matrix    editDP(s1, s2)    # Function to print all ways    printWays(s1, s2, []) | 
C#
| usingSystem;usingSystem.Collections.Generic;classProgram{    // Create List of lists that will store all sets of operations    staticList<List<string>> arrs = newList<List<string>>();    staticint[,] dp = newint[1001, 1001];    // Function to print all ways    staticvoidPrintAllChanges(strings1, strings2, List<string> changes)    {        inti = s1.Length;        intj = s2.Length;        // Iterate till the end        while(true)        {            if(i == 0 || j == 0)            {                // Add this list to our List of lists.                arrs.Add(newList<string>(changes));                break;            }            // If same            if(s1[i - 1] == s2[j - 1])            {                i--;                j--;            }            else            {                boolif1 = false, if2 = false;                // Replace                if(dp[i, j] == dp[i - 1, j - 1] + 1)                {                    // Add this step                    changes.Add("Change "+ s1[i - 1] + " to "+ s2[j - 1]);                    i--;                    j--;                    if1 = true;                }                // Delete                if(dp[i, j] == dp[i - 1, j] + 1)                {                    if(!if1)                    {                        changes.Add("Delete "+ s1[i - 1]);                        i--;                    }                    else                    {                        // If the previous method was true,                        // create a new list as a copy of the previous.                        List<string> changes2 = newList<string>(changes);                        changes2.RemoveAt(changes2.Count - 1);                        // Add this new operation                        changes2.Add("Delete "+ s1[i]);                        // Initiate a new instance of this function with remaining substrings                        PrintAllChanges(s1.Substring(0, i), s2.Substring(0, j + 1), changes2);                    }                    if2 = true;                }                // Add character step                if(dp[i, j] == dp[i, j - 1] + 1)                {                    if(!if1 && !if2)                    {                        changes.Add("Add "+ s2[j - 1]);                        j--;                    }                    else                    {                        // Add steps                        List<string> changes2 = newList<string>(changes);                        changes2.RemoveAt(changes2.Count - 1);                        changes2.Add("Add "+ s2[j]);                        // Recursively call for the next steps                        PrintAllChanges(s1.Substring(0, i + 1), s2.Substring(0, j), changes2);                    }                }            }        }    }    // Function to compute the DP matrix    staticvoidEditDP(strings1, strings2)    {        intl1 = s1.Length;        intl2 = s2.Length;        // Initialize by the maximum edits possible        for(inti = 0; i <= l1; i++)            dp[i, 0] = i;        for(intj = 0; j <= l2; j++)            dp[0, j] = j;        // Compute the DP matrix        for(inti = 1; i <= l1; i++)        {            for(intj = 1; j <= l2; j++)            {                // If the characters are the same, no changes required                if(s1[i - 1] == s2[j - 1])                    dp[i, j] = dp[i - 1, j - 1];                else                    // Minimum of three operations possible                    dp[i, j] = Math.Min(dp[i - 1, j - 1], Math.Min(dp[i - 1, j], dp[i, j - 1])) + 1;            }        }    }    staticvoidPrintWays(strings1, strings2, List<string> changes)    {        // Function to print all the ways        PrintAllChanges(s1, s2, newList<string>());        inti = 1;        // Print all the possible ways        foreach(varar inarrs)        {            Console.WriteLine("\nMethod "+ i + " : ");            foreach(vars inar)            {                Console.WriteLine(s);            }            i++;        }    }    // Driver Code    staticvoidMain()    {        strings1 = "abcdef";        strings2 = "axcdfdh";        // Calculate the DP matrix        EditDP(s1, s2);        // Function to print all ways        PrintWays(s1, s2, newList<string>());    }} | 
Javascript
| // JavaScript program to print all the possible// steps to change a string to another// create List of lists that will store all sets of// operationslet arrs = [];let dp = newArray(1001).fill(null).map(() => newArray(1001).fill(0));// Function to print all waysfunctionprintAllChanges(s1, s2, changes) {    let i = s1.length;    let j = s2.length;    // Iterate till end    while(true) {        if(i === 0 || j === 0) {            // Add this list to our List of lists.            arrs.push(changes.slice());            break;        }        // If same        if(s1[i - 1] === s2[j - 1]) {            i--;            j--;        } else{            let if1 = false,                if2 = false;            // Replace            if(dp[i][j] === dp[i - 1][j - 1] + 1) {                // Add this step                changes.push(`Change ${s1[i - 1]} to ${s2[j - 1]}`);                i--;                j--;                if1 = true;            }            // Delete            if(dp[i][j] === dp[i - 1][j] + 1) {                if(!if1) {                    changes.push(`Delete ${s1[i - 1]}`);                    i--;                } else{                    // If the previous method was true,                    // create a new list as a copy of                    // previous.                    let changes2 = changes.slice(0, -1);                    // Add this new operation                    changes2.push(`Delete ${s1[i]}`);                    // initiate new new instance of this                    // function with remaining substrings                    printAllChanges(s1.slice(0, i), s2.slice(0, j + 1), changes2);                }                if2 = true;            }            // Add character step            if(dp[i][j] === dp[i][j - 1] + 1) {                if(!if1 && !if2) {                    changes.push(`Add ${s2[j - 1]}`);                    j--;                } else{                    // Add steps                    let changes2 = changes.slice(0, -1);                    changes2.push(`Add ${s2[j]}`);                    // Recursively call for the next steps                    printAllChanges(s1.slice(0, i + 1), s2.slice(0, j), changes2);                }            }        }    }}// Function to compute the DP matrixfunctioneditDP(s1, s2) {    let l1 = s1.length;    let l2 = s2.length;    // initialize by the maximum edits possible    for(let i = 0; i <= l1; i++) {        dp[i][0] = i;    }    for(let j = 0; j <= l2; j++) {        dp[0][j] = j;    }    // Compute the DP matrix    for(let i = 1; i <= l1; i++) {        for(let j = 1; j <= l2; j++) {            // if the characters are same            // no changes required            if(s1[i - 1] === s2[j - 1]) {                dp[i][j] = dp[i - 1][j - 1];            } else{                // minimum of three operations possible                dp[i][j] = Math.min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1;            }        }    }}functionprintWays(s1, s2, changes) {    // Function to print all the ways    printAllChanges(s1, s2, []);    let i = 1;    // print all the possible ways    for(let ar of arrs) {        console.log(`\nMethod ${i++} : `);        for(let s of ar) {            console.log(s);        }    }}// Driver Codelet s1 = "abcdef";let s2 = "axcdfdh";// calculate the DP matrixeditDP(s1, s2);// Function to print all waysprintWays(s1, s2, []);// Contributed by adityasharmadev01 | 
Method 1 : Add h Change f to d Change e to f Change b to x Method 2 : Change f to h Add d Change e to f Change b to x Method 3 : Change f to h Change e to d Add f Change b to x
Time Complexity: O(m*n*n*k) m – length of s1, n – length of s2, second n caused by fact that we copy ‘changes’ every time there is more than one way found, k – num of all possible ways, upper-bound for k= 3^n
Space Complexity: O(n^2) due to the use of the dp array
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!
 
				 
					


