Given two string S and T, the task is to find the minimum length prefix from S which consists of all characters of string T. If S does not contain all characters of string T, print -1.
Examples:
Input: S = “MarvoloGaunt”, T = “Tom”
Output: 12
Explanation:
The 12 length prefix “MarvoloGaunt” contains all the characters of “Tom”Input: S = “TheWorld”, T = “Dio”
Output: -1
Explanation:
The string “TheWorld” does not contain the character ‘i’ from the string “Dio”.
Naive Approach:
The simplest approach to solve the problem is to iterate the string S and compare the frequency of each letter in both the prefix and T and return the length traversed if the required prefix is found. Otherwise, return -1.
Time Complexity: O(N2)
Auxiliary Space: O(1)
Efficient Approach:
To optimize the above approach, follow the steps below:
- Store the frequencies of T in a dictionary dictCount.
- Store the number of unique letters with a count greater than 0 as nUnique.
- Iterate over [0, N], and obtain the ith index character of S as ch.
- Decrease the count of ch from dictCount if it exists. If this count goes to 0, decrease nUnique by 1.
- If nUnique reaches 0, return the length traversed till then.
- After complete traversal of S, if nUnique still exceeds 0, print -1.
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; int getPrefixLength(string srcStr, string targetStr) { // Base Case - if T is empty, // it matches 0 length prefix if (targetStr.length() == 0) return 0; // Convert strings to lower // case for uniformity transform(srcStr.begin(), srcStr.end(), srcStr.begin(), :: tolower ); transform(targetStr.begin(), targetStr.end(), targetStr.begin(), :: tolower ); map< char , int > dictCount; int nUnique = 0; // Update dictCount to the // letter count of T for ( char ch: targetStr) { // If new character is found, // initialize its entry, // and increase nUnique if (dictCount.find(ch) == dictCount.end()) { nUnique += 1; dictCount[ch] = 0; } // Increase count of ch dictCount[ch] += 1; } // Iterate from 0 to N for ( int i = 0; i < srcStr.length(); i++) { // i-th character char ch = srcStr[i]; // Skip if ch not in targetStr if (dictCount.find(ch) == dictCount.end()) continue ; // Decrease Count dictCount[ch] -= 1; // If the count of ch reaches 0, // we do not need more ch, // and can decrease nUnique if (dictCount[ch] == 0) nUnique -= 1; // If nUnique reaches 0, // we have found required prefix if (nUnique == 0) return (i + 1); } // Otherwise return -1; } // Driver code int main() { string S = "MarvoloGaunt" ; string T = "Tom" ; cout << getPrefixLength(S, T); return 0; } // This code is contributed by divyeshrabadiya07 |
Java
// Java program for the above approach import java.util.*; public class Main { public static int getPrefixLength(String srcStr, String targetStr) { // Base Case - if T is empty, // it matches 0 length prefix if (targetStr.length() == 0 ) return 0 ; // Convert strings to lower // case for uniformity srcStr = srcStr.toLowerCase(); targetStr = targetStr.toLowerCase(); HashMap<Character, Integer> dictCount = new HashMap<>(); int nUnique = 0 ; // Update dictCount to the // letter count of T for ( char ch : targetStr.toCharArray()) { // If new character is found, // initialize its entry, // and increase nUnique if (dictCount.containsKey(ch) != true ) { nUnique += 1 ; dictCount.put(ch, 0 ); } // Increase count of ch dictCount.replace(ch, dictCount.get(ch) + 1 ); } // Iterate from 0 to N for ( int i = 0 ; i < srcStr.length(); i++) { // i-th character char ch = srcStr.charAt(i); // Skip if ch not in targetStr if (dictCount.containsKey(ch) != true ) continue ; // Decrease Count dictCount.replace(ch, dictCount.get(ch) - 1 ); // If the count of ch reaches 0, // we do not need more ch, // and can decrease nUnique if (dictCount.get(ch) == 0 ) nUnique -= 1 ; // If nUnique reaches 0, // we have found required prefix if (nUnique == 0 ) return (i + 1 ); } // Otherwise return - 1 ; } // Driver code public static void main(String[] args) { String S = "MarvoloGaunt" ; String T = "Tom" ; System.out.println(getPrefixLength(S, T)); } } // This code is contributed by divyesh072019 |
Python3
# Python3 program for the above approach def getPrefixLength(srcStr, targetStr): # Base Case - if T is empty, # it matches 0 length prefix if ( len (targetStr) = = 0 ): return 0 # Convert strings to lower # case for uniformity srcStr = srcStr.lower() targetStr = targetStr.lower() dictCount = dict ([]) nUnique = 0 # Update dictCount to the # letter count of T for ch in targetStr: # If new character is found, # initialize its entry, # and increase nUnique if (ch not in dictCount): nUnique + = 1 dictCount[ch] = 0 # Increase count of ch dictCount[ch] + = 1 # Iterate from 0 to N for i in range ( len (srcStr)): # i-th character ch = srcStr[i] # Skip if ch not in targetStr if (ch not in dictCount): continue # Decrease Count dictCount[ch] - = 1 # If the count of ch reaches 0, # we do not need more ch, # and can decrease nUnique if (dictCount[ch] = = 0 ): nUnique - = 1 # If nUnique reaches 0, # we have found required prefix if (nUnique = = 0 ): return (i + 1 ) # Otherwise return - 1 # Driver Code if __name__ = = "__main__" : S = "MarvoloGaunt" T = "Tom" print (getPrefixLength(S, T)) |
C#
// C# program for the above approach using System.Collections.Generic; using System; class GFG{ static int getPrefixLength( string srcStr, string targetStr) { // Base Case - if T is empty, // it matches 0 length prefix if (targetStr.Length == 0) return 0; // Convert strings to lower // case for uniformity srcStr = srcStr.ToLower(); targetStr = targetStr.ToLower(); Dictionary< char , int > dictCount = new Dictionary< char , int >(); int nUnique = 0; // Update dictCount to the // letter count of T foreach ( var ch in targetStr) { // If new character is found, // initialize its entry, // and increase nUnique if (dictCount.ContainsKey(ch) != true ) { nUnique += 1; dictCount[ch] = 0; } // Increase count of ch dictCount[ch] += 1; } // Iterate from 0 to N for ( int i = 0; i < srcStr.Length; i++) { // i-th character char ch = srcStr[i]; // Skip if ch not in targetStr if (dictCount.ContainsKey(ch) != true ) continue ; // Decrease Count dictCount[ch] -= 1; // If the count of ch reaches 0, // we do not need more ch, // and can decrease nUnique if (dictCount[ch] == 0) nUnique -= 1; // If nUnique reaches 0, // we have found required prefix if (nUnique == 0) return (i + 1); } // Otherwise return -1; } // Driver code public static void Main() { string S = "MarvoloGaunt" ; string T = "Tom" ; Console.Write(getPrefixLength(S, T)); } } // This code is contributed by Stream_Cipher |
Javascript
<script> // JavaScript program for the above approach function getPrefixLength(srcStr, targetStr) { // Base Case - if T is empty, // it matches 0 length prefix if (targetStr.length === 0) return 0; // Convert strings to lower // case for uniformity srcStr = srcStr.toLowerCase(); targetStr = targetStr.toLowerCase(); var dictCount = {}; var nUnique = 0; // Update dictCount to the // letter count of T for (const ch of targetStr) { // If new character is found, // initialize its entry, // and increase nUnique if (dictCount.hasOwnProperty(ch) !== true ) { nUnique += 1; dictCount[ch] = 0; } // Increase count of ch dictCount[ch] += 1; } // Iterate from 0 to N for ( var i = 0; i < srcStr.length; i++) { // i-th character var ch = srcStr[i]; // Skip if ch not in targetStr if (dictCount.hasOwnProperty(ch) !== true ) continue ; // Decrease Count dictCount[ch] -= 1; // If the count of ch reaches 0, // we do not need more ch, // and can decrease nUnique if (dictCount[ch] === 0) nUnique -= 1; // If nUnique reaches 0, // we have found required prefix if (nUnique === 0) return i + 1; } // Otherwise return -1; } // Driver code var S = "MarvoloGaunt" ; var T = "Tom" ; document.write(getPrefixLength(S, T)); </script> |
12
Time Complexity: O(N)
Auxiliary Space: O(1)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!