Given two strings A and B, the task is to split the string A into the minimum number of substrings such that each substring is in the string B.
Note: If there is no way to split the string, then print -1
Examples:
Input: A = “abcdab”, B = “dabc”
Output: 2
Explanation:
The two substrings of A which is also present in B are –
{“abc”, “dab”}
Input: A = “abcde”, B = “edcb”
Output: -1
Explanation:
There is no way to split the string A into substring
Such that each string is also present in the B.
Approach:
- Construct a trie of every substring of B.
- After that, we’ll use Dynamic programing to find the minimum number of parts to break the string A such that every part is a substring of B.
Recurrence Relation in Dynamic Programming:
dp[i] = minimum number of parts to break the string A up to ith prefix.
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.
Below is the implementation of the above approach:
C++
// C++ implementation to split the // string into minimum number of // parts such that each part is also // present in the another string #include <bits/stdc++.h> 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< int > 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 |
2
Time Complexity :
Space Complexity :