📌  相关文章
📜  最小化包含另一个字符串T的所有字符的字符串S的前缀长度

📅  最后修改于: 2021-04-22 01:43:19             🧑  作者: Mango

给定两个字符串ST ,任务是从S中查找最小长度的前缀,该前缀由字符串T的所有字符组成。如果S不包含字符串T的所有字符,则打印-1

例子:

天真的方法:
解决问题的最简单方法是迭代字符串S ,比较前缀和T中每个字母的频率,如果找到所需的前缀,则返回遍历的长度。否则,返回-1。

时间复杂度: O(N 2 )
辅助空间: O(1)

高效方法:
要优化上述方法,请按照以下步骤操作:

  1. T的频率存储在字典dictCount中
  2. 将计数大于0的唯一字母数存储为nUnique
  3. [0,N]进行迭代,并获得S的i索引字符ch
  4. dictCount减少ch的计数(如果存在)。如果该计数变为0,则将nUnique减小1。
  5. 如果nUnique达到0,则返回到此为止遍历的长度。
  6. 在完成S的遍历之后,如果nUnique仍然超过0,则打印-1

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
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 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 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 dictCount = new Dictionary();
                                                
    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


输出:
12

时间复杂度: O(N)
辅助空间: O(1)