📌  相关文章
📜  使用Binary Search具有K个唯一字符的最长子字符串

📅  最后修改于: 2021-05-07 06:54:43             🧑  作者: Mango

给定一个字符串str和一个整数K ,任务是打印具有恰好K个唯一字符的最长子字符串的长度。如果有一个以上可能的最长子串,则打印其中任何一个,如果没有这样的子串,则打印-1

例子:

方法:本文讨论了一种解决此问题的方法。在本文中,将讨论基于二进制搜索的方法。将对至少具有K个唯一字符的子字符串的长度应用二进制搜索。假设我们尝试使用长度len并检查是否存在大小为len的子字符串,该子字符串至少包含k个唯一字符。如果可能,则尝试通过从该长度搜索到最大可能的长度(即输入字符串的大小)来最大化大小。如果不可能,则搜索较小尺寸的len。
要检查二进制搜索给出的长度是否有k个唯一字符,可以使用一组插入所有字符,然后如果set的大小小于k,则不可能给出答案,否则二进制搜索给出的答案是最大的答案。
二进制搜索在这里适用,因为已知对于某个len是否可行,并且我们希望将len最大化,因此搜索域会发生变化,然后从len到n进行搜索。

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
  
// Function that returns true if there
// is a substring of length len
// with <=k unique characters
bool isValidLen(string s, int len, int k)
{
  
    // Size of the string
    int n = s.size();
  
    // Map to store the characters
    // and their frequency
    unordered_map mp;
    int right = 0;
  
    // Update the map for the
    // first substring
    while (right < len) {
        mp[s[right]]++;
        right++;
    }
  
    if (mp.size() <= k)
        return true;
  
    // Check for the rest of the substrings
    while (right < n) {
  
        // Add the new character
        mp[s[right]]++;
  
        // Remove the first character
        // of the previous window
        mp[s[right - len]]--;
  
        // Update the map
        if (mp[s[right - len]] == 0)
            mp.erase(s[right - len]);
        if (mp.size() <= k)
            return true;
        right++;
    }
    return mp.size() <= k;
}
  
// Function to return the length of the
// longest substring which has K
// unique characters
int maxLenSubStr(string s, int k)
{
  
    // Check if the complete string
    // contains K unique characters
    set uni;
    for (auto x : s)
        uni.insert(x);
    if (uni.size() < k)
        return -1;
  
    // Size of the string
    int n = s.size();
  
    // Apply binary search
    int lo = -1, hi = n + 1;
    while (hi - lo > 1) {
        int mid = lo + hi >> 1;
        if (isValidLen(s, mid, k))
            lo = mid;
        else
            hi = mid;
    }
    return lo;
}
  
// Driver code
int main()
{
    string s = "aabacbebebe";
    int k = 3;
  
    cout << maxLenSubStr(s, k);
  
    return 0;
}


Java
// Java implementation of the approach
import java.util.*;
  
class GFG 
{
  
    // Function that returns true if there
    // is a subString of length len
    // with <=k unique characters
    static boolean isValidLen(String s, 
                              int len, int k) 
    {
  
        // Size of the String
        int n = s.length();
  
        // Map to store the characters
        // and their frequency
        Map mp = new HashMap();
        int right = 0;
  
        // Update the map for the
        // first subString
        while (right < len)
        {
            if (mp.containsKey(s.charAt(right))) 
            {
                mp.put(s.charAt(right), 
                mp.get(s.charAt(right)) + 1);
            } 
            else
            {
                mp.put(s.charAt(right), 1);
            }
            right++;
        }
  
        if (mp.size() <= k)
            return true;
  
        // Check for the rest of the subStrings
        while (right < n) 
        {
  
            // Add the new character
            if (mp.containsKey(s.charAt(right))) 
            {
                mp.put(s.charAt(right), 
                mp.get(s.charAt(right)) + 1);
            } 
            else 
            {
                mp.put(s.charAt(right), 1);
            }
  
            // Remove the first character
            // of the previous window
            if (mp.containsKey(s.charAt(right - len)))
            {
                mp.put(s.charAt(right - len),
                mp.get(s.charAt(right - len)) - 1);
            }
  
            // Update the map
            if (mp.get(s.charAt(right - len)) == 0)
                mp.remove(s.charAt(right - len));
            if (mp.size() <= k)
                return true;
            right++;
        }
        return mp.size() <= k;
    }
  
    // Function to return the length of the
    // longest subString which has K
    // unique characters
    static int maxLenSubStr(String s, int k) 
    {
  
        // Check if the complete String
        // contains K unique characters
        Set uni = new HashSet();
        for (Character x : s.toCharArray())
            uni.add(x);
        if (uni.size() < k)
            return -1;
  
        // Size of the String
        int n = s.length();
  
        // Apply binary search
        int lo = -1, hi = n + 1;
        while (hi - lo > 1) 
        {
            int mid = lo + hi >> 1;
            if (isValidLen(s, mid, k))
                lo = mid;
            else
                hi = mid;
        }
        return lo;
    }
  
    // Driver code
    public static void main(String[] args) 
    {
        String s = "aabacbebebe";
        int k = 3;
  
        System.out.print(maxLenSubStr(s, k));
    }
}
  
// This code is contributed by Rajput-Ji


Python3
# Python3 implementation of the approach
  
# Function that returns True if there
# is a sub of length len
# with <=k unique characters
def isValidLen(s, lenn, k):
  
    # Size of the
    n = len(s)
  
    # Map to store the characters
    # and their frequency
    mp = dict()
    right = 0
  
    # Update the map for the
    # first sub
    while (right < lenn):
        mp[s[right]] = mp.get(s[right], 0) + 1
        right += 1
  
    if (len(mp) <= k):
        return True
  
    # Check for the rest of the subs
    while (right < n):
  
        # Add the new character
        mp[s[right]] = mp.get(s[right], 0) + 1
  
        # Remove the first character
        # of the previous window
        mp[s[right - lenn]] -= 1
  
        # Update the map
        if (mp[s[right - lenn]] == 0):
            del mp[s[right - lenn]]
        if (len(mp) <= k):
            return True
        right += 1
  
    return len(mp)<= k
  
# Function to return the length of the
# longest sub which has K
# unique characters
def maxLenSubStr(s, k):
  
    # Check if the complete
    # contains K unique characters
    uni = dict()
    for x in s:
        uni[x] = 1
    if (len(uni) < k):
        return -1
  
    # Size of the
    n = len(s)
  
    # Apply binary search
    lo = -1
    hi = n + 1
    while (hi - lo > 1):
        mid = lo + hi >> 1
        if (isValidLen(s, mid, k)):
            lo = mid
        else:
            hi = mid
  
    return lo
  
# Driver code
s = "aabacbebebe"
k = 3
  
print(maxLenSubStr(s, k))
  
# This code is contributed by Mohit Kumar


C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
  
class GFG 
{
  
    // Function that returns true if there
    // is a subString of length len
    // with <=k unique characters
    static bool isValidLen(String s, 
                           int len, int k) 
    {
  
        // Size of the String
        int n = s.Length;
  
        // Map to store the characters
        // and their frequency
        Dictionary mp = new Dictionary();
        int right = 0;
  
        // Update the map for the
        // first subString
        while (right < len)
        {
            if (mp.ContainsKey(s[right])) 
            {
                mp[s[right]] = mp[s[right]] + 1;
            } 
            else
            {
                mp.Add(s[right], 1);
            }
            right++;
        }
  
        if (mp.Count <= k)
            return true;
  
        // Check for the rest of the subStrings
        while (right < n) 
        {
  
            // Add the new character
            if (mp.ContainsKey(s[right])) 
            {
                mp[s[right]] = mp[s[right]] + 1;
            } 
            else
            {
                mp.Add(s[right], 1);
            }
  
            // Remove the first character
            // of the previous window
            if (mp.ContainsKey(s[right - len]))
            {
                mp[s[right - len]] = mp[s[right - len]] - 1;
            }
  
            // Update the map
            if (mp[s[right - len]] == 0)
                mp.Remove(s[right - len]);
            if (mp.Count <= k)
                return true;
            right++;
        }
        return mp.Count <= k;
    }
  
    // Function to return the length of the
    // longest subString which has K
    // unique characters
    static int maxLenSubStr(String s, int k) 
    {
  
        // Check if the complete String
        // contains K unique characters
        HashSet uni = new HashSet();
        foreach (char x in s.ToCharArray())
            uni.Add(x);
        if (uni.Count < k)
            return -1;
  
        // Size of the String
        int n = s.Length;
  
        // Apply binary search
        int lo = -1, hi = n + 1;
        while (hi - lo > 1) 
        {
            int mid = lo + hi >> 1;
            if (isValidLen(s, mid, k))
                lo = mid;
            else
                hi = mid;
        }
        return lo;
    }
  
    // Driver code
    public static void Main(String[] args) 
    {
        String s = "aabacbebebe";
        int k = 3;
  
        Console.Write(maxLenSubStr(s, k));
    }
}
  
// This code is contributed by Rajput-Ji


输出:
7