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++ 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 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 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# 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 |
<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)