📌  相关文章
📜  具有频率大于或等于子字符串一半的字符的最大子字符串的长度

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

给定一个字符串S ,该字符串由从’a’到’z’的字符组成。任务是找到S的最大子字符串的长度,该字符串包含一个字符,该字符的频率在子字符串中大于或等于子字符串长度的一半。

注意:对于奇数长度的子字符串,要计算半长,请考虑整数除法。例如,11的一半是5。

例子:

Input : S = "ababbbacbcbcca" 
Output : 13
Substring from index 1(0-based indexing) to index 13, 
"babbbacbcbcca" have b's frequency equals to 6 which is 
equal to half of the length of substring (13/2 = 6).
 
Input : S = "abcde"
Output : 3

简单方法:想法是找到S的所有子串,并为每个子串找到每个字符的频率,并将其与子串长度的一半进行比较。现在,在满足条件的所有子串中,输出长度最大的子串的长度。

高效的方法
首先,观察只能有26在字符串S所以明显不同的字符,考虑对于具有频率大于或等于子字符串的长度被一个每个字符之一。

因此,为了找到满足条件的可能的最长子字符串的长度,对于每个字符,我们将使该字符的计数成为前缀数组。例如,对于S =“ abacdaef”,“ a”的前缀数组将为freq [] ,[1,1,2,2,2,2,3,3,3]。

我们正在寻找满足以下条件的条件:

freq[r] - freq[l - 1] >= (r - l)/2, where l, r are the indices.

另外,我们可以写

(2 * freq[r]) - r >= (2 * freq[l - 1]) - l

因此,找到两个数组r []l [] ,其中r [i] =(2 * freq [i])– i和l [i] =(2 * freq [l – 1])– l,为1 <= i <= S的长度

现在,对于r []中的每个i ,使用二进制搜索找到l []的下界,以使l []中的索引最小,例如j。

因此, i – j + 1是解决方案之一,找到最大值。

然后为每个字符循环上述方法。

下面是上述方法的实现:

C++
// C++ implementation of the above approach
  
#include 
using namespace std;
  
// Function to return the length of the longest 
// sub string having frequency of a character 
// greater than half of the length of the 
// sub string
int maxLength(string s, int n)
{
    int ans = INT_MIN;
    vector A, L, R;
    int freq[n + 5];
  
    // for each of the character 'a' to 'z'
    for (int i = 0; i < 26; i++) {
        int count = 0;
        memset(freq, 0, sizeof freq);
  
        // finding frequency prefix array of the 
        // character
        for (int j = 0; j < n; j++) {
            if (s[j] - 'a' == i)
                count++;
            freq[j] = count;
        }
  
        // Finding the r[] and l[] arrays.
        for (int j = 0; j < n; j++) {
            L.push_back((2 * freq[j - 1]) - j);
            R.push_back((2 * freq[j]) - j);
        }
  
        int max_len = INT_MIN;
        int min_val = INT_MAX;
  
        // for each j from 0 to n
        for (int j = 0; j < n; j++) {
            min_val = min(min_val, L[j]);
            A.push_back(min_val);
  
            int l = 0, r = j;
  
            // Finding the lower bound of i.
            while (l <= r) {
                int mid = (l + r) >> 1;
                if (A[mid] <= R[j]) {
                    max_len = max(max_len, j - mid + 1);
                    r = mid - 1;
                }
                else {
                    l = mid + 1;
                }
            }
        }
  
        // storing the maximum value of i - j + 1
        ans = max(ans, max_len);
  
        // clearing all the vector so that it clearing
        // be use for other character.
        A.clear();
        R.clear();
        L.clear();
    }
  
    return ans;
}
  
// Driver Code
int main()
{
    string s = "ababbbacbcbcca";
    int n = s.length();
  
    cout << maxLength(s, n) << '\n';
      
    return 0;
}


Java
// Java implementation of the above approach
import java.util.*;
  
class GFG 
{
  
// Function to return the length of the longest 
// sub string having frequency of a character 
// greater than half of the length of the 
// sub string
static int maxLength(String s, int n)
{
    int ans = Integer.MIN_VALUE;
    Vector A = new Vector();
    Vector L = new Vector();
    Vector R = new Vector();
  
    int []freq = new int[n + 5];
  
    // for each of the character 'a' to 'z'
    for (int i = 0; i < 26; i++) 
    {
        int count = 0;
          
        // finding frequency prefix array of the 
        // character
        for (int j = 0; j < n; j++) 
        {
            if (s.charAt(j) - 'a' == i)
                count++;
            freq[j] = count;
        }
  
        // Finding the r[] and l[] arrays.
        for (int j = 1; j < n; j++) 
        {
            L.add((2 * freq[j - 1]) - j);
            R.add((2 * freq[j]) - j);
        }
  
        int max_len = Integer.MIN_VALUE;
        int min_val = Integer.MAX_VALUE;
  
        // for each j from 0 to n
        for (int j = 0; j < L.size(); j++) 
        {
            min_val = Math.min(min_val, L.get(j));
            A.add(min_val);
  
            int l = 0, r = j;
  
            // Finding the lower bound of i.
            while (l <= r) 
            {
                int mid = (l + r) >> 1;
                if (A.get(mid) <= R.get(j)) 
                {
                    max_len = Math.max(max_len, 
                                       j - mid + 1);
                    r = mid - 1;
                }
                else 
                {
                    l = mid + 1;
                }
            }
        }
  
        // storing the maximum value of i - j + 1
        ans = Math.max(ans, max_len);
  
        // clearing all the vector so that it clearing
        // be use for other character.
        A.clear();
        R.clear();
        L.clear();
    }
    return ans;
}
  
// Driver Code
public static void main(String[] args)
{
    String s = "ababbbacbcbcca";
    int n = s.length();
  
    System.out.println(maxLength(s, n));
}
}
  
// This code is contributed by Princi Singh


Python3
# Python3 implementation of the above approach 
import sys
  
# Function to return the length 
# of the longest sub string 
# having frequency of a character 
# greater than half of the length 
# of the sub string 
def maxLength(s, n) :
      
    ans = -(sys.maxsize + 1); 
    A, L, R = [], [], []; 
    freq = [0] * (n + 5); 
  
    # for each of the character 'a' to 'z' 
    for i in range(26) :
        count = 0; 
          
        # finding frequency prefix array 
        # of the character 
        for j in range(n) :
            if (ord(s[j]) - ord('a') == i) :
                count += 1; 
                  
            freq[j] = count; 
          
        # Finding the r[] and l[] arrays. 
        for j in range(n) : 
            L.append((2 * freq[j - 1]) - j); 
            R.append((2 * freq[j]) - j); 
          
        max_len = -(sys.maxsize + 1); 
        min_val = sys.maxsize ; 
  
        # for each j from 0 to n 
        for j in range(n) :
            min_val = min(min_val, L[j]); 
            A.append(min_val); 
  
            l = 0; r = j; 
  
            # Finding the lower bound of i. 
            while (l <= r) : 
                mid = (l + r) >> 1; 
                if (A[mid] <= R[j]) :
                    max_len = max(max_len, j - mid + 1); 
                    r = mid - 1; 
                  
                else :
                    l = mid + 1; 
  
        # storing the maximum value of i - j + 1 
        ans = max(ans, max_len); 
  
        # clearing all the vector so that it can
        # be used for other characters. 
        A.clear(); 
        R.clear(); 
        L.clear(); 
  
    return ans; 
  
# Driver Code 
if __name__ == "__main__" : 
  
    s = "ababbbacbcbcca"; 
    n = len(s); 
  
    print(maxLength(s, n));
  
# This code is contributed by AnkitRai01


C#
// C# implementation of the above approach
using System;
using System.Collections.Generic; 
  
class GFG 
{
  
// Function to return the length of the longest 
// sub string having frequency of a character 
// greater than half of the length of the 
// sub string
static int maxLength(String s, int n)
{
    int ans = int.MinValue;
    List A = new List();
    List L = new List();
    List R = new List();
  
    int []freq = new int[n + 5];
  
    // for each of the character 'a' to 'z'
    for (int i = 0; i < 26; i++) 
    {
        int count = 0;
          
        // finding frequency prefix array of the 
        // character
        for (int j = 0; j < n; j++) 
        {
            if (s[j] - 'a' == i)
                count++;
            freq[j] = count;
        }
  
        // Finding the r[] and l[] arrays.
        for (int j = 1; j < n; j++) 
        {
            L.Add((2 * freq[j - 1]) - j);
            R.Add((2 * freq[j]) - j);
        }
  
        int max_len = int.MinValue;
        int min_val = int.MaxValue;
  
        // for each j from 0 to n
        for (int j = 0; j < L.Count; j++) 
        {
            min_val = Math.Min(min_val, L[j]);
            A.Add(min_val);
  
            int l = 0, r = j;
  
            // Finding the lower bound of i.
            while (l <= r) 
            {
                int mid = (l + r) >> 1;
                if (A[mid] <= R[j]) 
                {
                    max_len = Math.Max(max_len, 
                                       j - mid + 1);
                    r = mid - 1;
                }
                else
                {
                    l = mid + 1;
                }
            }
        }
  
        // storing the maximum value of i - j + 1
        ans = Math.Max(ans, max_len);
  
        // clearing all the vector so that it can
        // be used for other characters.
        A.Clear();
        R.Clear();
        L.Clear();
    }
    return ans;
}
  
// Driver Code
public static void Main(String[] args)
{
    String s = "ababbbacbcbcca";
    int n = s.Length;
  
    Console.WriteLine(maxLength(s, n));
}
}
  
// This code is contributed by 29AjayKumar


输出:
13