📌  相关文章
📜  最小化给定字符串中的分区以获取另一个字符串

📅  最后修改于: 2022-05-13 01:57:07.266000             🧑  作者: Mango

最小化给定字符串中的分区以获取另一个字符串

给定两个字符串AB ,打印A中获得另一个字符串B所需的最小切片数。如果无法从A获得B ,则打印“-1”。

例子 :

方法:这个问题是最长公共子串问题的变体。做这个问题的主要思想是获取AB之间最长的公共子串,然后根据A 中公共子串的起始索引决定从 A切割该部分所需的切片数。然后用 1 片或 2 片从A中取出那部分。此外,从B中删除该子字符串,并在A的情况下将该子字符串替换为“0”或字母以外的任何内容。现在,请按照以下步骤解决此问题:

  • 首先,用AB的长度做一个简单的检查。如果B更长,则返回 -1。
  • 现在第一步是在两个字符串中找到最长的公共子字符串。
  • 现在,如果字符串A中该公共子字符串的开始索引或结束索引分别为 0 或N (A.length()-1) ,则只需 1 个切片即可将其切掉。
  • 如果子字符串在字符串A的第一个字符和最后一个字符之间,那么在这种情况下,需要 2 个切片来切掉该部分。
  • 现在,通过从中删除当前最长的子字符串来减小B的大小。这样做是必要的,因为这样会在下一次调用longSubstring()中选择不同的子字符串作为最长的公共子字符串。
  • 之后,将A中存在的公共子字符串替换为字符“0”。子字符串不能直接从A中删除,因为顺序很重要,因为我们使用A中存在的公共子字符串的索引来决定切片的数量。
  • 重复相同的过程,直到字符串B变为空。

下面是上述方法的实现:

Java
// Java program for the above approach
import java.io.*;
 
class GFG {
 
    // Function returning the ending points
    // of LCS and the length of LCS
    public static int[] longestSubString(
        String X, String Y)
    {
 
        // Find length of both the Strings.
        int m = X.length();
        int n = Y.length();
 
        // Variable to store length of
        // longest common subString.
        int result = 0;
 
        // Variable to store ending point of
        // longest common subString in X.
        int endIndexX = 0;
        int endIndexY = 0;
 
        // Matrix to store result of two
        // consecutive rows at a time.
        int cache[][] = new int[2][m + 1];
 
        // Variable to represent which row of
        // matrix is current row.
        int currentRow = 0;
 
        // For a particular value of i and j,
        // len[currRow][j] stores length of
        // longest common subString in
        // String X[0..i] and Y[0..j].
        for (int i = 0; i <= m; i++) {
            for (int j = 0; j <= n; j++) {
                if (i == 0 || j == 0) {
                    cache[currentRow][j] = 0;
                }
                else if (X.charAt(i - 1)
                         == Y.charAt(j - 1)) {
                    cache[currentRow][j]
                        = cache[1 -
                                currentRow][j
                                            - 1]
                        + 1;
                    if (cache[currentRow][j]
                        > result) {
                        result
                            = cache[currentRow][j];
                        endIndexX = i - 1;
                        endIndexY = j - 1;
                    }
                }
                else {
                    cache[currentRow][j] = 0;
                }
            }
 
            // Make current row as previous row and
            // previous row as new current row.
            currentRow = 1 - currentRow;
        }
 
        // Longest common subString is from index
        // (endIndexX - result + 1) in X and
        // (endIndexY - result + 1) in Y.
        int[] array = new int[] { (endIndexX
                                   - result
                                   + 1),
                                  (endIndexY
                                   - result
                                   + 1),
                                  result };
        return array;
    }
 
    // Function to replace used substring in A with 0's
    public static String processString(String A,
                                       int index,
                                       int length)
    {
        String X = A.substring(0, index);
        String Y = "";
 
        // Insering "0" in place
        // of that substring.
        for (int i = 0; i < length; i++) {
            Y += "0";
        }
 
        String Z = A.substring(index
                               + length);
        return (X + Y + Z);
    }
 
    // Function to return the minimum
    // number of slices required.
    public static int minimumSlice(String A,
                                   String B)
    {
        // Checking the length of A and B.
        if (A.length() < B.length())
            return -1;
 
        // If both are equal no slice required.
        if (A.equals(B))
            return 0;
 
        int result = 0, n = (A.length() - 1);
 
        // Loop continues until B is empty.
        while (!B.isEmpty()) {
            int[] processed
                = longestSubString(A, B);
            if (processed[2] == 0)
                return -1;
 
            // Incrementing result by 1 if
            // longest substring start at index 0
            // or the end point is equal to n
            if ((processed[0]
                 + processed[2] - 1 == n)
                || processed[0] == 0) {
 
                // Result should only
                // be incremented if
                // character just before
                // and after the
                // substring is not "0";
                // if "0" is there,
                // then the slice
                // has already been counted
                if (processed[0] == 0) {
                    if (A.charAt(processed[0]
                                 + processed[2])
                        != '0')
                        result++;
                }
                else {
                    if (A.charAt(processed[0] - 1)
                        != '0')
                        result++;
                }
            }
 
            // In any other case increment it by 2
            else {
 
                // Result should only
                // be incremented if
                // character just before
                // and after the substring
                // is not "0";
                // if "0" is there,
                // then the slice has
                // already been counted.
                if (A.charAt(processed[0]
                             + processed[2])
                    != '0') {
                    result++;
                }
 
                if (A.charAt(processed[0] - 1)
                    != '0') {
                    result++;
                }
            }
 
            // Reducing the size of B by
            // removing current longest
            // substring from it.
            B = B.substring(0, processed[1])
                + B.substring(processed[1]
                              + processed[2]);
 
            // Clearing the used substring from A.
            A = processString(A, processed[0],
                              processed[2]);
        }
        return result;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        System.out.println(minimumSlice("topgames", "mepo"));
    }
}


Python3
# Python 3 program for the above approach
 
# Function returning the ending points
# of LCS and the length of LCS
 
 
def longestSubString(
        X,  Y):
 
    # Find length of both the Strings.
    m = len(X)
    n = len(Y)
 
    # Variable to store length of
    # longest common subString.
    result = 0
 
    # Variable to store ending point of
    # longest common subString in X.
    endIndexX = 0
    endIndexY = 0
 
    # Matrix to store result of two
    # consecutive rows at a time.
    cache = [[0 for x in range(m+1)] for y in range(2)]
 
    # Variable to represent which row of
    # matrix is current row.
    currentRow = 0
 
    # For a particular value of i and j,
    # len[currRow][j] stores length of
    # longest common subString in
    # String X[0..i] and Y[0..j].
    for i in range(m + 1):
        for j in range(n + 1):
            if (i == 0 or j == 0):
                cache[currentRow][j] = 0
 
            elif (X[i - 1] == Y[j - 1]):
                cache[currentRow][j] = cache[1 - currentRow][j - 1] + 1
                if (cache[currentRow][j]
                        > result):
                    result = cache[currentRow][j]
                    endIndexX = i - 1
                    endIndexY = j - 1
            else:
                cache[currentRow][j] = 0
 
        # Make current row as previous row and
        # previous row as new current row.
        currentRow = 1 - currentRow
 
    # Longest common subString is from index
    # (endIndexX - result + 1) in X and
    # (endIndexY - result + 1) in Y.
    array = [(endIndexX
              - result
              + 1),
             (endIndexY
              - result
              + 1),
             result]
    return array
 
# Function to replace used substring in A with 0's
 
 
def processString(A, index, length):
 
    X = A[0: index]
    Y = ""
 
    # Insering "0" in place
    # of that substring.
    for i in range(length):
        Y += "0"
 
    Z = A[index + length:]
    return (X + Y + Z)
 
# Function to return the minimum
# number of slices required.
 
 
def minimumSlice(A,
                 B):
 
    # Checking the length of A and B.
    if (len(A) < len(B)):
        return -1
 
    # If both are equal no slice required.
    if (A == B):
        return 0
 
    result = 0
    n = (len(A) - 1)
 
    # Loop continues until B is empty.
    while (len(B) != 0):
        processed = longestSubString(A, B)
        if (processed[2] == 0):
            return -1
 
        # Incrementing result by 1 if
        # longest substring start at index 0
        # or the end point is equal to n
        if ((processed[0]
             + processed[2] - 1 == n)
                or processed[0] == 0):
 
            # Result should only
            # be incremented if
            # character just before
            # and after the
            # substring is not "0"
            # if "0" is there,
            # then the slice
            # has already been counted
            if (processed[0] == 0):
                if (A[processed[0] + processed[2]] != '0'):
                    result += 1
 
            else:
                if (A[processed[0] - 1] != '0'):
                    result += 1
 
        # In any other case increment it by 2
        else:
 
            # Result should only
            # be incremented if
            # character just before
            # and after the substring
            # is not "0"
            # if "0" is there,
            # then the slice has
            # already been counted.
            if (A[processed[0]
                  + processed[2]]
                    != '0'):
                result += 1
 
            if (A[processed[0] - 1] != '0'):
                result += 1
 
        # Reducing the size of B by
        # removing current longest
        # substring from it.
        B = B[0:processed[1]] + B[processed[1] + processed[2]:]
 
        # Clearing the used substring from A.
        A = processString(A, processed[0],
                          processed[2])
 
    return result
 
# Driver Code
if __name__ == "__main__":
 
    print(minimumSlice("topgames", "mepo"))
 
    # This code is contributed by ukasp.


C#
// C# program for the above approach
 
using System;
class GFG
{
 
    // Function returning the ending points
    // of LCS and the length of LCS
    public static int[] longestSubstring(string X, string Y)
    {
 
        // Find length of both the strings.
        int m = X.Length;
        int n = Y.Length;
 
        // Variable to store length of
        // longest common substring.
        int result = 0;
 
        // Variable to store ending point of
        // longest common substring in X.
        int endIndexX = 0;
        int endIndexY = 0;
 
        // Matrix to store result of two
        // consecutive rows at a time.
        int[,] cache = new int[2, m + 1];
 
        // Variable to represent which row of
        // matrix is current row.
        int currentRow = 0;
 
        // For a particular value of i and j,
        // len[currRow][j] stores length of
        // longest common substring in
        // string X[0..i] and Y[0..j].
        for (int i = 0; i <= m; i++)
        {
            for (int j = 0; j <= n; j++)
            {
                if (i == 0 || j == 0)
                {
                    cache[currentRow, j] = 0;
                }
                else if (X[i - 1] == Y[j - 1])
                {
                    cache[currentRow, j]
                        = cache[1 - currentRow, j - 1]
                        + 1;
                    if (cache[currentRow, j]
                        > result)
                    {
                        result
                            = cache[currentRow, j];
                        endIndexX = i - 1;
                        endIndexY = j - 1;
                    }
                }
                else
                {
                    cache[currentRow, j] = 0;
                }
            }
 
            // Make current row as previous row and
            // previous row as new current row.
            currentRow = 1 - currentRow;
        }
 
        // Longest common substring is from index
        // (endIndexX - result + 1) in X and
        // (endIndexY - result + 1) in Y.
        int[] array = new int[] { (endIndexX
                                   - result
                                   + 1),
                                  (endIndexY
                                   - result
                                   + 1),
                                  result };
        return array;
    }
 
    // Function to replace used substring in A with 0's
    public static string processstring(string A,
                                       int index,
                                       int length)
    {
        string X = A.Substring(0, index);
        string Y = "";
 
        // Insering "0" in place
        // of that substring.
        for (int i = 0; i < length; i++)
        {
            Y += "0";
        }
 
        string Z = A.Substring(index
                               + length);
        return (X + Y + Z);
    }
 
    // Function to return the minimum
    // number of slices required.
    public static int minimumSlice(string A,
                                   string B)
    {
        // Checking the length of A and B.
        if (A.Length < B.Length)
            return -1;
 
        // If both are equal no slice required.
        if (A.Equals(B))
            return 0;
 
        int result = 0, n = (A.Length - 1);
 
        // Loop continues until B is empty.
        while (B.Length != 0)
        {
            int[] processed
                = longestSubstring(A, B);
            if (processed[2] == 0)
                return -1;
 
            // Incrementing result by 1 if
            // longest substring start at index 0
            // or the end point is equal to n
            if ((processed[0]
                 + processed[2] - 1 == n)
                || processed[0] == 0)
            {
 
                // Result should only
                // be incremented if
                // character just before
                // and after the
                // substring is not "0";
                // if "0" is there,
                // then the slice
                // has already been counted
                if (processed[0] == 0)
                {
                    if (A[processed[0] + processed[2]]
                        != '0')
                        result++;
                }
                else
                {
                    if (A[processed[0] - 1]
                        != '0')
                        result++;
                }
            }
 
            // In any other case increment it by 2
            else
            {
 
                // Result should only
                // be incremented if
                // character just before
                // and after the substring
                // is not "0";
                // if "0" is there,
                // then the slice has
                // already been counted.
                if (A[processed[0] + processed[2]]
                    != '0')
                {
                    result++;
                }
 
                if (A[processed[0] - 1]
                    != '0')
                {
                    result++;
                }
            }
 
            // Reducing the size of B by
            // removing current longest
            // substring from it.
            B = B.Substring(0, processed[1])
                + B.Substring(processed[1]
                              + processed[2]);
 
            // Clearing the used substring from A.
            A = processstring(A, processed[0],
                              processed[2]);
        }
        return result;
    }
 
    // Driver Code
    public static void Main()
    {
        Console.Write(minimumSlice("topgames", "mepo"));
    }
}
 
// This code is contributed by gfgking.



输出
5

时间复杂度: O(N*(M 2 )) 其中 N 是字符串A 的长度,M 是字符串B 的长度
辅助空间: O(M)