给定一个字符串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