📌  相关文章
📜  打印将一个字符串转换为另一个字符串的所有可能方法 |编辑距离

📅  最后修改于: 2021-09-22 09:55:02             🧑  作者: Mango

先决条件:动态规划 |组 5(编辑距离)
给定两个字符串str1 和 str2,任务是打印将“str1”转换为“str2”的所有可能方式。
以下是可以对“str1”执行的操作:

  1. 插入
  2. 消除
  3. 代替

以上所有操作都是等价的。任务是使用所需的最少编辑(操作)次数打印将“str1”转换为“str2”的所有各种方式,其中“方式”包括所需的所有此类操作的系列。
例子:

打印一种可能方式的方法:

这篇文章已经讨论了寻找最小编辑次数的方法。要打印一种可能的方式,请从使用最小编辑距离方法形成的 DP 矩阵的右下角进行迭代。检查两个字符串与该元素有关的字符是否相等。如果是,则表示不需要编辑,DP[i][j] 是从 DP[i-1][j-1] 复制而来的。

If str1[i-1] == str2[j-1], proceed diagonally. 

请注意,由于 DP 矩阵在 0 索引处包含一个额外的行和列,因此字符串索引将减一。即DP[i][j]对应str1的i-1索引和str2的j-1索引。
现在,如果字符不相等,则表示该矩阵元素 DP[i][j] 是从 DP[i-1][j-1]、DP[i][j-1] 和 DP 的最小值中获得的[i-1][j],加 1。因此,检查这个元素的来源。

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.

一旦到达任一字符串的结尾即 (i==0 或 j==0 ),就完成将一个字符串转换为另一个字符串。我们将打印所需的所有操作集。
下面是上述方法的实现:

C++
// C++ program to print one possible
// way of converting a string to another
#include 
using namespace std;
 
int DP[100][100];
 
// Function to print the steps
void printChanges(string s1, string s2,
                         int dp[][100])
{
    int i = s1.length();
    int j = s2.length();
 
    // check till the end
    while (i and j)
    {
        // if characters are same
        if (s1[i - 1] == s2[j - 1])
        {
            i--;
            j--;
        }
 
        // Replace
        else if (dp[i][j] == dp[i - 1][j - 1] + 1)
        {
            cout << "change " << s1[i - 1]
                 << " to " << s2[j - 1] << endl;
            i--;
            j--;
        }
 
        // Delete the character
        else if (dp[i][j] == dp[i - 1][j] + 1)
        {
            cout << "Delete " << s1[i - 1] << endl;
            i--;
        }
 
        // Add the character
        else if (dp[i][j] == dp[i][j - 1] + 1)
        {
            cout << "Add " << s2[j - 1] << endl;
            j--;
        }
    }
}
 
// Function to compute the DP matrix
void editDP(string s1, string s2)
{
    int l1 = s1.length();
    int l2 = s2.length();
    DP[l1 + 1][l2 + 1];
 
    // initialize by the maximum edits possible
    for (int i = 0; i <= l1; i++)
        DP[i][0] = i;
    for (int j = 0; j <= l2; j++)
        DP[0][j] = j;
 
    // Compute the DP matrix
    for (int i = 1; i <= l1; i++)
    {
        for (int 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] = min(min(DP[i - 1][j - 1],
                                   DP[i - 1][j]),
                                   DP[i][j - 1]) + 1;
        }
    }
 
    // print the steps
    printChanges(s1, s2, DP);
}
// Driver Code
int main()
{
    string s1 = "abcdef";
    string s2 = "axcdfdh";
 
    // calculate the DP matrix
    editDP(s1, s2);
 
    return 0;
}
 
// This code is contributed by
// sanjeev2552


Java
// Java program to print one possible
// way of converting a string to another
import java.util.*;
 
public class Edit_Distance {
    static int dp[][];
 
    // Function to print the steps
    static void printChanges(String s1, String s2)
    {
        int i = s1.length();
        int j = s2.length();
 
        // check till the end
        while (i != 0 && j != 0) {
 
            // if characters are same
            if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                i--;
                j--;
            }
 
            // Replace
            else if (dp[i][j] == dp[i - 1][j - 1] + 1) {
                System.out.println("change " + s1.charAt(i - 1) + " to " + s2.charAt(j - 1));
                i--;
                j--;
            }
 
            // Delete the character
            else if (dp[i][j] == dp[i - 1][j] + 1) {
                System.out.println("Delete " + s1.charAt(i - 1));
                i--;
            }
 
            // Add the character
            else if (dp[i][j] == dp[i][j - 1] + 1) {
                System.out.println("Add " + s2.charAt(j - 1));
                j--;
            }
        }
    }
 
    // Function to compute the DP matrix
    static void editDP(String s1, String s2)
    {
        int l1 = s1.length();
        int l2 = s2.length();
        int[][] DP = new int[l1 + 1][l2 + 1];
 
        // initialize by the maximum edits possible
        for (int i = 0; i <= l1; i++)
            DP[i][0] = i;
        for (int j = 0; j <= l2; j++)
            DP[0][j] = j;
 
        // Compute the DP matrix
        for (int i = 1; i <= l1; i++) {
            for (int j = 1; j <= l2; j++) {
 
                // if the characters are same
                // no changes required
                if (s1.charAt(i - 1) == s2.charAt(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
    static int min(int a, int b, int c)
    {
        int z = Math.min(a, b);
        return Math.min(z, c);
    }
 
    // Driver Code
    public static void main(String[] args) throws Exception
    {
        String s1 = "abcdef";
        String s2 = "axcdfdh";
 
        // calculate the DP matrix
        editDP(s1, s2);
 
        // print the steps
        printChanges(s1, s2);
    }
}


Python3
# Python3 program to print one possible
# way of converting a string to another
 
# Function to print the steps
def printChanges(s1, s2, dp):
     
    i = len(s1)
    j = len(s2)
     
   # Check till the end
    while(i > 0 and j > 0):
         
        # If characters are same
        if s1[i - 1] == s2[j - 1]:
            i -= 1
            j -= 1
             
        # Replace
        elif dp[i][j] == dp[i - 1][j - 1] + 1:
            print("change", s1[i - 1],
                      "to", s2[j - 1])
            j -= 1
            i -= 1
             
        # Delete
        elif dp[i][j] == dp[i - 1][j] + 1:
            print("Delete", s1[i - 1])
            i -= 1
             
        # Add
        elif dp[i][j] == dp[i][j - 1] + 1:
            print("Add", s2[j - 1])
            j -= 1
             
# Function to compute the DP matrix
def editDP(s1, s2):
     
    len1 = len(s1)
    len2 = len(s2)
    dp = [[0 for i in range(len2 + 1)]
             for j in range(len1 + 1)]
     
    # Initialize by the maximum edits possible
    for i in range(len1 + 1):
        dp[i][0] = i
    for j in range(len2 + 1):
        dp[0][j] = j
     
    # Compute the DP Matrix
    for i in range(1, len1 + 1):
        for j in range(1, len2 + 1):
             
            # If the characters are same
            # no changes required
            if s2[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 Matrix
editDP(s1, s2)
 
# This code is contributed by Pranav S


C#
// C# program to print one possible
// way of converting a string to another
using System;
 
public class Edit_Distance
{
    static int [,]dp;
 
    // Function to print the steps
    static void printChanges(String s1, String s2)
    {
        int i = s1.Length;
        int j = 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
            else if (dp[i, j] == dp[i - 1, j - 1] + 1)
            {
                Console.WriteLine("change " + s1[i - 1] + " to " + s2[j - 1]);
                i--;
                j--;
            }
 
            // Delete the character
            else if (dp[i, j] == dp[i - 1, j] + 1)
            {
                Console.WriteLine("Delete " + s1[i - 1]);
                i--;
            }
 
            // Add the character
            else if (dp[i, j] == dp[i, j - 1] + 1)
            {
                Console.WriteLine("Add " + s2[j - 1]);
                j--;
            }
        }
    }
 
    // Function to compute the DP matrix
    static void editDP(String s1, String s2)
    {
        int l1 = s1.Length;
        int l2 = s2.Length;
        int[,] DP = new int[l1 + 1, l2 + 1];
 
        // initialize by the maximum edits possible
        for (int i = 0; i <= l1; i++)
            DP[i, 0] = i;
        for (int j = 0; j <= l2; j++)
            DP[0, j] = j;
 
        // Compute the DP matrix
        for (int i = 1; i <= l1; i++)
        {
            for (int 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
                {
 
                    // minimu 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
    static int min(int a, int b, int c)
    {
        int z = Math.Min(a, b);
        return Math.Min(z, c);
    }
 
    // Driver Code
    public static void Main(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


Java
// Java program to print all the possible
// steps to change a string to another
import java.util.ArrayList;
 
public class Edit_Distance {
    static int dp[][];
 
    // create List of lists that will store all sets of operations
    static ArrayList > arrs =
                              new ArrayList >();
 
    // Function to print all ways
    static void printAllChanges(String s1,
                                String s2, ArrayList changes)
    {
 
        int i = s1.length();
        int j = s2.length();
 
        // Iterate till end
        while (true) {
 
            if (i == 0 || j == 0) {
 
                // Add this list to our List of lists.
                arrs.add(changes);
                break;
            }
 
            // If same
            if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                i--;
                j--;
            }
 
            else {
                boolean if1 = false, if2 = false;
 
                // Replace
                if (dp[i][j] == dp[i - 1][j - 1] + 1) {
 
                    // Add this step
                    changes.add("Change " + s1.charAt(i - 1)
                                + " to " + s2.charAt(j - 1));
                    i--;
                    j--;
 
                    // note whether this 'if' was true.
                    if1 = true;
                }
 
                // Delete
                if (dp[i][j] == dp[i - 1][j] + 1) {
                    if (if1 == false) {
                        changes.add("Delete " + s1.charAt(i - 1));
                        i--;
                    }
                    else {
                        // If the previous method was true,
                        // create a new list as a copy of previous.
                        ArrayList changes2 = new ArrayList();
                        changes2.addAll(changes);
 
                        // Remove last operation
                        changes2.remove(changes.size() - 1);
 
                        // Add this new operation
                        changes2.add("Delete " + s1.charAt(i));
 
                        // initiate new 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 == false && if2 == false) {
                        changes.add("Add " + s2.charAt(j - 1));
                        j--;
                    }
                    else {
 
                        // Add steps
                        ArrayList changes2 = new ArrayList();
                        changes2.addAll(changes);
                        changes2.remove(changes.size() - 1);
                        changes2.add("Add " + s2.charAt(j));
 
                        // Recursively call for the next steps
                        printAllChanges(s1.substring(0, i + 1),
                                        s2.substring(0, j), changes2);
                    }
                }
            }
        }
    }
 
    // Function to compute the DP matrix
    static void editDP(String s1, String s2)
    {
        int l1 = s1.length();
        int l2 = s2.length();
        int[][] DP = new int[l1 + 1][l2 + 1];
 
        // initialize by the maximum edits possible
        for (int i = 0; i <= l1; i++)
            DP[i][0] = i;
        for (int j = 0; j <= l2; j++)
            DP[0][j] = j;
 
        // Compute the DP matrix
        for (int i = 1; i <= l1; i++) {
            for (int j = 1; j <= l2; j++) {
 
                // if the characters are same
                // no changes required
                if (s1.charAt(i - 1) == s2.charAt(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
    static int min(int a, int b, int c)
    {
        int z = Math.min(a, b);
        return Math.min(z, c);
    }
    static void printWays(String s1, String s2,
                          ArrayList changes)
    {
 
        // Function to print all the ways
        printAllChanges(s1, s2, new ArrayList());
 
        int i = 1;
 
        // print all the possible ways
        for (ArrayList ar : arrs) {
            System.out.println("\nMethod " + i++ + " : \n");
            for (String s : ar) {
                System.out.println(s);
            }
        }
    }
 
    // Driver Code
    public static void main(String[] args) throws Exception
    {
        String s1 = "abcdef";
        String s2 = "axcdfdh";
 
        // calculate the DP matrix
        editDP(s1, s2);
 
        // Function to print all ways
        printWays(s1, s2, new ArrayList());
    }
}


输出:
change f to h
change e to d
Add f
change b to x

打印所有可能方式的方法:

创建将存储所需操作的字符串集合。该集合可以是 C++ 中的字符串向量或Java的字符串列表。添加操作就像之前打印它们到这个集合。然后创建这些集合的集合,这些集合将存储多个方法(字符串操作集)。
之前使用 Else-if 来检查我们从哪里导出 DP[i][j]。现在,检查所有 If 以查看是否有超过 1 种方法可以获得该元素。如果有,我们从之前创建一个新集合,删除最后一个操作,添加这个新操作并使用这个新列表启动这个函数的另一个实例。以这种方式,每当有将 str1 更改为 str2 的新方法时添加新列表,每次都获得一个新方法。
在到达任一字符串的末尾时,将此列表添加到列表的集合中,从而完成所有可能操作的集合,并将它们添加。
下面是上述方法的实现:

Java

// Java program to print all the possible
// steps to change a string to another
import java.util.ArrayList;
 
public class Edit_Distance {
    static int dp[][];
 
    // create List of lists that will store all sets of operations
    static ArrayList > arrs =
                              new ArrayList >();
 
    // Function to print all ways
    static void printAllChanges(String s1,
                                String s2, ArrayList changes)
    {
 
        int i = s1.length();
        int j = s2.length();
 
        // Iterate till end
        while (true) {
 
            if (i == 0 || j == 0) {
 
                // Add this list to our List of lists.
                arrs.add(changes);
                break;
            }
 
            // If same
            if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                i--;
                j--;
            }
 
            else {
                boolean if1 = false, if2 = false;
 
                // Replace
                if (dp[i][j] == dp[i - 1][j - 1] + 1) {
 
                    // Add this step
                    changes.add("Change " + s1.charAt(i - 1)
                                + " to " + s2.charAt(j - 1));
                    i--;
                    j--;
 
                    // note whether this 'if' was true.
                    if1 = true;
                }
 
                // Delete
                if (dp[i][j] == dp[i - 1][j] + 1) {
                    if (if1 == false) {
                        changes.add("Delete " + s1.charAt(i - 1));
                        i--;
                    }
                    else {
                        // If the previous method was true,
                        // create a new list as a copy of previous.
                        ArrayList changes2 = new ArrayList();
                        changes2.addAll(changes);
 
                        // Remove last operation
                        changes2.remove(changes.size() - 1);
 
                        // Add this new operation
                        changes2.add("Delete " + s1.charAt(i));
 
                        // initiate new 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 == false && if2 == false) {
                        changes.add("Add " + s2.charAt(j - 1));
                        j--;
                    }
                    else {
 
                        // Add steps
                        ArrayList changes2 = new ArrayList();
                        changes2.addAll(changes);
                        changes2.remove(changes.size() - 1);
                        changes2.add("Add " + s2.charAt(j));
 
                        // Recursively call for the next steps
                        printAllChanges(s1.substring(0, i + 1),
                                        s2.substring(0, j), changes2);
                    }
                }
            }
        }
    }
 
    // Function to compute the DP matrix
    static void editDP(String s1, String s2)
    {
        int l1 = s1.length();
        int l2 = s2.length();
        int[][] DP = new int[l1 + 1][l2 + 1];
 
        // initialize by the maximum edits possible
        for (int i = 0; i <= l1; i++)
            DP[i][0] = i;
        for (int j = 0; j <= l2; j++)
            DP[0][j] = j;
 
        // Compute the DP matrix
        for (int i = 1; i <= l1; i++) {
            for (int j = 1; j <= l2; j++) {
 
                // if the characters are same
                // no changes required
                if (s1.charAt(i - 1) == s2.charAt(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
    static int min(int a, int b, int c)
    {
        int z = Math.min(a, b);
        return Math.min(z, c);
    }
    static void printWays(String s1, String s2,
                          ArrayList changes)
    {
 
        // Function to print all the ways
        printAllChanges(s1, s2, new ArrayList());
 
        int i = 1;
 
        // print all the possible ways
        for (ArrayList ar : arrs) {
            System.out.println("\nMethod " + i++ + " : \n");
            for (String s : ar) {
                System.out.println(s);
            }
        }
    }
 
    // Driver Code
    public static void main(String[] args) throws Exception
    {
        String s1 = "abcdef";
        String s2 = "axcdfdh";
 
        // calculate the DP matrix
        editDP(s1, s2);
 
        // Function to print all ways
        printWays(s1, s2, new ArrayList());
    }
}
输出:
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

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程