📌  相关文章
📜  将字符串拆分为最小部分,使每个部分都在另一个字符串

📅  最后修改于: 2021-09-17 06:55:08             🧑  作者: Mango

给定两个字符串AB ,任务是将字符串A 拆分为最少数量的子字符串,使得每个子字符串都在字符串B 中。
注意:如果没有办法分割字符串,则打印-1
例子:

方法:

  • 构造 B 的每个子串的 trie。
  • 之后,我们将使用动态规划来找到打破字符串A 的最小部分数,使得每个部分都是 B 的子字符串。

动态规划中的递归关系:

dp[0] = 0
for i in {0, S1.length}
    for j in {i, S1.length}
        if(S1[i, ... j] is found in trie
            dp[j] = min(dp[j], dp[i] + 1);
        else
            break;

dp[S1.length] is the
minimum number of parts.

下面是上述方法的实现:

C++
// C++ implementation to split the
// string into minimum number of
// parts such that each part is also
// present in the another string
 
#include 
using namespace std;
 
const int INF = 1e9 + 9;
 
// Node of Trie
struct TrieNode {
    TrieNode* child[26] = { NULL };
};
 
// Function to insert a node in the
// Trie Data Structure
void insert(int idx, string& s,
            TrieNode* root)
{
    TrieNode* temp = root;
    for (int i = idx; i < s.length(); i++) {
 
        // Inserting every character from idx
        // till end to string into trie
        if (temp->child[s[i] - 'a'] == NULL)
 
            // if there is no edge corresponding
            // to the ith character,
            // then make a new node
            temp->child[s[i] - 'a'] = new TrieNode;
 
        temp = temp->child[s[i] - 'a'];
    }
}
 
// Function to find the minimum
// number of parts such that each
// part is present into another string
int minCuts(string S1, string S2)
{
    int n1 = S1.length();
    int n2 = S2.length();
 
    // Making a new trie
    TrieNode* root = new TrieNode;
 
    for (int i = 0; i < n2; i++) {
 
        // Inserting every substring
        // of S2 in trie
        insert(i, S2, root);
    }
 
    // Creating dp array and
    // init it with infinity
    vector dp(n1 + 1, INF);
 
    // Base Case
    dp[0] = 0;
    for (int i = 0; i < n1; i++) {
 
        // Starting the cut from ith character
        // taking temporary node pointer
        // for checking whether the substring
        // [i, j) is present in trie of not
        TrieNode* temp = root;
        for (int j = i + 1; j <= n1; j++) {
            if (temp->child[S1[j - 1] - 'a'] == NULL)
 
                // if the jth character is not in trie
                // we'll break
                break;
 
            // Updating the the ending of
            // jth character with dp[i] + 1
            dp[j] = min(dp[j], dp[i] + 1);
 
            // Descending the trie pointer
            temp = temp->child[S1[j - 1] - 'a'];
        }
    }
 
    // Answer not possible
    if (dp[n1] >= INF)
        return -1;
    else
        return dp[n1];
}
 
// Driver Code
int main()
{
    string S1 = "abcdab";
    string S2 = "dabc";
 
    cout << minCuts(S1, S2);
}


Java
// Java implementation to split the
// String into minimum number of
// parts such that each part is also
// present in the another String
import java.util.*;
 
class GFG{
 
static int INF = (int)(1e9 + 9);
 
// Node of Trie
static class TrieNode
{
    TrieNode []child = new TrieNode[26];
};
 
// Function to insert a node in the
// Trie Data Structure
static void insert(int idx, String s,
                   TrieNode root)
{
    TrieNode temp = root;
    for(int i = idx; i < s.length(); i++)
    {
         
        // Inserting every character from idx
        // till end to String into trie
        if (temp.child[s.charAt(i) - 'a'] == null)
 
            // If there is no edge corresponding
            // to the ith character,
            // then make a new node
            temp.child[s.charAt(i) - 'a'] = new TrieNode();
 
        temp = temp.child[s.charAt(i) - 'a'];
    }
}
 
// Function to find the minimum
// number of parts such that each
// part is present into another String
static int minCuts(String S1, String S2)
{
    int n1 = S1.length();
    int n2 = S2.length();
 
    // Making a new trie
    TrieNode root = new TrieNode();
 
    for(int i = 0; i < n2; i++)
    {
         
        // Inserting every subString
        // of S2 in trie
        insert(i, S2, root);
    }
 
    // Creating dp array and
    // init it with infinity
    int []dp = new int[n1 + 1];
    Arrays.fill(dp, INF);
     
    // Base Case
    dp[0] = 0;
     
    for(int i = 0; i < n1; i++)
    {
         
        // Starting the cut from ith character
        // taking temporary node pointer
        // for checking whether the subString
        // [i, j) is present in trie of not
        TrieNode temp = root;
        for(int j = i + 1; j <= n1; j++)
        {
            if (temp.child[S1.charAt(j - 1) - 'a'] == null)
 
                // If the jth character is not in trie
                // we'll break
                break;
 
            // Updating the the ending of
            // jth character with dp[i] + 1
            dp[j] = Math.min(dp[j], dp[i] + 1);
 
            // Descending the trie pointer
            temp = temp.child[S1.charAt(j - 1) - 'a'];
        }
    }
 
    // Answer not possible
    if (dp[n1] >= INF)
        return -1;
    else
        return dp[n1];
}
 
// Driver Code
public static void main(String[] args)
{
    String S1 = "abcdab";
    String S2 = "dabc";
 
    System.out.print(minCuts(S1, S2));
}
}
 
// This code is contributed by Rajput-Ji


Python3
# Python3 implementation to split the
# string into minimum number of
# parts such that each part is also
# present in the another string
INF = 1e9 + 9
 
# Node of Trie
class TrieNode():
    def __init__(self):
 
        self.child = [None] * 26
 
# Function to insert a node in the
# Trie Data Structure
def insert(idx, s, root):
     
    temp = root
 
    for i in range(idx, len(s)):
         
        # Inserting every character from idx
        # till end to string into trie
        if temp.child[ord(s[i]) -
                      ord('a')] == None:
             
            # If there is no edge corresponding
            # to the ith character,
            # then make a new node
            temp.child[ord(s[i]) -
                       ord('a')] = TrieNode()
 
        temp = temp.child[ord(s[i]) - ord('a')]
 
# Function to find the minimum
# number of parts such that each
# part is present into another string
def minCuts(S1, S2):
     
    n1 = len(S1)
    n2 = len(S2)
 
    # Making a new trie
    root = TrieNode()
 
    for i in range(n2):
         
        # Inserting every substring
        # of S2 in trie
        insert(i, S2, root)
 
    # Creating dp array and
    # init it with infinity
    dp = [INF] * (n1 + 1)
 
    # Base Case
    dp[0] = 0
 
    for i in range(n1):
         
        # Starting the cut from ith character
        # taking temporary node pointer
        # for checking whether the substring
        # [i, j) is present in trie of not
        temp = root
        for j in range(i + 1, n1 + 1):
            if temp.child[ord(S1[j - 1]) -
                          ord('a')] == None:
                 
                # If the jth character is not
                # in trie we'll break
                break
 
            # Updating the the ending of
            # jth character with dp[i] + 1
            dp[j] = min(dp[j], dp[i] + 1)
 
            # Descending the trie pointer
            temp = temp.child[ord(S1[j - 1]) -
                              ord('a')]
 
    # Answer not possible
    if dp[n1] >= INF:
        return -1
    else:
        return dp[n1]
 
# Driver Code
S1 = "abcdab"
S2 = "dabc"
 
print(minCuts(S1, S2))
 
# This code is contributed by Shivam Singh


C#
// C# implementation to split the
// String into minimum number of
// parts such that each part is also
// present in the another String
using System;
class GFG{
 
static int INF = (int)(1e9 + 9);
 
// Node of Trie
class TrieNode
{
    public TrieNode []child =
                    new TrieNode[26];
};
 
// Function to insert a node in the
// Trie Data Structure
static void insert(int idx, String s,
                   TrieNode root)
{
    TrieNode temp = root;
    for(int i = idx; i < s.Length; i++)
    {       
        // Inserting every character from idx
        // till end to String into trie
        if (temp.child[s[i] - 'a'] == null)
 
            // If there is no edge corresponding
            // to the ith character,
            // then make a new node
            temp.child[s[i] - 'a'] =
                       new TrieNode();
 
        temp = temp.child[s[i] - 'a'];
    }
}
 
// Function to find the minimum
// number of parts such that each
// part is present into another String
static int minCuts(String S1, String S2)
{
    int n1 = S1.Length;
    int n2 = S2.Length;
 
    // Making a new trie
    TrieNode root = new TrieNode();
 
    for(int i = 0; i < n2; i++)
    {       
        // Inserting every subString
        // of S2 in trie
        insert(i, S2, root);
    }
 
    // Creating dp array and
    // init it with infinity
    int []dp = new int[n1 + 1];
    for(int i = 0; i <= n1; i++)
        dp[i] = INF;
     
    // Base Case
    dp[0] = 0;
     
    for(int i = 0; i < n1; i++)
    {       
        // Starting the cut from ith character
        // taking temporary node pointer
        // for checking whether the subString
        // [i, j) is present in trie of not
        TrieNode temp = root;
        for(int j = i + 1; j <= n1; j++)
        {
            if (temp.child[S1[j-1] - 'a'] == null)
 
                // If the jth character is not in trie
                // we'll break
                break;
 
            // Updating the the ending of
            // jth character with dp[i] + 1
            dp[j] = Math.Min(dp[j], dp[i] + 1);
 
            // Descending the trie pointer
            temp = temp.child[S1[j - 1] - 'a'];
        }
    }
 
    // Answer not possible
    if (dp[n1] >= INF)
        return -1;
    else
        return dp[n1];
}
 
// Driver Code
public static void Main(String[] args)
{
    String S1 = "abcdab";
    String S2 = "dabc";
    Console.Write(minCuts(S1, S2));
}
}
// This code is contributed by shikhasingrajput


Javascript


输出:
2

时间复杂度:

O(N^2)

空间复杂度:

O(N^2)