给定一个大小为N的字符串S仅由字符a 、 b和c 组成,任务是找到给定字符串S的子串数,使得字符a的频率大于字符c的频率。
例子:
Input: S = “abcc”
Output: 2
Explanation:
Below are all the possible substrings of S(= “abcc”) having the frequency of the character greater than the character c:
- “a”: The frequency of a and c is 1 and 0 respectively.
- “ab”: The frequency of a and c is 1 and 0 respectively.
Therefore, the count of such substrings is 2.
Input: S = “abcabcabcaaaaabbbccccc”
Output: 148
朴素方法:解决给定问题的最简单方法是生成给定字符串S 的所有可能子字符串,并计算字符‘a’计数大于字符‘c’计数的那些子字符串。检查所有子字符串后,打印总计数的值作为结果。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the number of
// substrings having the frequency of
// 'a' greater than frequency of 'c'
void countSubstrings(string& s)
{
// Stores the size of the string
int n = s.length();
// Stores the resultant
// count of substrings
int ans = 0;
// Traverse the given string
for (int i = 0; i < n; i++) {
// Store the difference between
// frequency of 'a' and 'c'
int cnt = 0;
// Traverse all substrings
// begining at index i
for (int j = i; j < n; j++) {
if (s[j] == 'a')
cnt++;
else if (s[j] == 'c')
cnt--;
// If the frequency of 'a'
// is greater than 'c'
if (cnt > 0) {
ans++;
}
}
}
// Print the answer
cout << ans;
}
// Drive Code
int main()
{
string S = "abccaab";
countSubstrings(S);
return 0;
}
Java
// Java program for the above approach
public class GFG
{
// Function to find the number of
// substrings having the frequency of
// 'a' greater than frequency of 'c'
public static void countSubstrings(String s)
{
// Stores the size of the string
int n = s.length();
// Stores the resultant
// count of substrings
int ans = 0;
// Traverse the given string
for (int i = 0; i < n; i++) {
// Store the difference between
// frequency of 'a' and 'c'
int cnt = 0;
// Traverse all substrings
// begining at index i
for (int j = i; j < n; j++) {
if (s.charAt(j) == 'a')
cnt++;
else if (s.charAt(j) == 'c')
cnt--;
// If the frequency of 'a'
// is greater than 'c'
if (cnt > 0) {
ans++;
}
}
}
// Print the answer
System.out.println(ans);
}
// Drive Code
public static void main(String args[])
{
String S = "abccaab";
countSubstrings(S);
}
}
// This code is contributed by SoumikMondal
Python3
# python program for the above approach
# Function to find the number of
# substrings having the frequency of
# 'a' greater than frequency of 'c'
def countSubstrings(s):
# Stores the size of the string
n = len(s)
# Stores the resultant
# count of substrings
ans = 0
# Traverse the given string
for i in range(n):
# Store the difference between
# frequency of 'a' and 'c'
cnt = 0
# Traverse all substrings
# begining at index i
for j in range(i, n):
if (s[j] == 'a'):
cnt += 1
elif (s[j] == 'c'):
cnt -= 1
# If the frequency of 'a'
# is greater than 'c'
if (cnt > 0):
ans+=1
# Prthe answer
print (ans)
# Drive Code
if __name__ == '__main__':
S = "abccaab"
countSubstrings(S)
# This code is contributed by mohit kumar 29.
Javascript
C++
// C++ program for the above approach
#include
using namespace std;
// Function to update the segment Tree
void update(int ind, vector& segTree,
int n)
{
// Update the value of ind
ind += n;
// Increment the leaf node
segTree[ind]++;
for (; ind > 1; ind >>= 1) {
// Update the parent nodes
segTree[ind >> 1] = segTree[ind]
+ segTree[ind ^ 1];
}
}
// Function to get the sum of all the
// elements between low to high - 1
int query(int low, int high,
vector& segTree, int n)
{
// Initialize the leaf nodes of
// the segment tree
low += n;
high += n;
int ans = 0;
while (low < high) {
// Node lies completely in the
// range of low to high
if (low % 2) {
ans += segTree[low];
low++;
}
if (high % 2) {
high--;
ans += segTree[high];
}
// Update the value of nodes
low >>= 1;
high >>= 1;
}
return ans;
}
// Function to count the number of
// substrings which have frequency of
// 'a' greater than frequency of 'c'.
void countSubstrings(string& s)
{
// Store the size of the string
int n = s.length();
// Intialize segment tree
vector segTree(4 * n);
int count = 0;
// Update the initial value of
// the count
update(n, segTree, 2 * n);
// Stores the required result
int ans = 0;
// Traverse the given string
for (int i = 0; i < n; i++) {
// Increment count
if (s[i] == 'a')
count++;
// Decrement count
else if (s[i] == 'c')
count--;
// Query the segment tree to
// find the sum of all values
// less than count
int val = query(0, n + count,
segTree, 2 * n);
ans += val;
// Update the current value of
// count in the segment tree
update(n + count, segTree, 2 * n);
}
// Print the answer
cout << ans;
}
// Driver Code
int main()
{
string S = "abccaab";
countSubstrings(S);
return 0;
}
输出:
11
时间复杂度: O(N 2 )
辅助空间: O(1)
高效方法:上述方法也可以通过使用 Segment Tree 进行优化。这个想法是在段树节点中存储字符串S 的所有前缀的字符‘a’和‘c’的频率差异。请按照以下步骤解决问题:
- 初始化一个变量,比如count为0 ,以存储字符‘a’和‘c’频率之间的差异。
- 初始化一个变量,比如ans为0 ,以存储字符‘a’的频率大于‘c’的子串的计数。
- 用全0初始化段树,这将在遍历字符串更新。
- 由于字符‘a’和‘c’的频率差异也可以为负,因此段树上的所有更新操作都将在将N添加到要更新的索引后完成,以避免出现负索引。
- 更新段树中索引(0 + N)的值,因为计数的初始值为0 。
- 在[0, N – 1]范围内遍历给定的字符串S并执行以下步骤:
- 如果当前字符是 ‘a’,则将计数增加1 。否则,如果当前字符是“c”的,然后由1递减计数。
- 对线段树执行查询以找到小于count的所有值的总和,因为所有这些子字符串的频率‘a’大于‘c’并将返回的值存储在变量 say val 中。
- 将val的值添加到变量ans 。
- 由索引处的值递增更新线段树被1(计数+ N)。
- 完成上述步骤后,将ans的值打印为子串的结果计数。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to update the segment Tree
void update(int ind, vector& segTree,
int n)
{
// Update the value of ind
ind += n;
// Increment the leaf node
segTree[ind]++;
for (; ind > 1; ind >>= 1) {
// Update the parent nodes
segTree[ind >> 1] = segTree[ind]
+ segTree[ind ^ 1];
}
}
// Function to get the sum of all the
// elements between low to high - 1
int query(int low, int high,
vector& segTree, int n)
{
// Initialize the leaf nodes of
// the segment tree
low += n;
high += n;
int ans = 0;
while (low < high) {
// Node lies completely in the
// range of low to high
if (low % 2) {
ans += segTree[low];
low++;
}
if (high % 2) {
high--;
ans += segTree[high];
}
// Update the value of nodes
low >>= 1;
high >>= 1;
}
return ans;
}
// Function to count the number of
// substrings which have frequency of
// 'a' greater than frequency of 'c'.
void countSubstrings(string& s)
{
// Store the size of the string
int n = s.length();
// Intialize segment tree
vector segTree(4 * n);
int count = 0;
// Update the initial value of
// the count
update(n, segTree, 2 * n);
// Stores the required result
int ans = 0;
// Traverse the given string
for (int i = 0; i < n; i++) {
// Increment count
if (s[i] == 'a')
count++;
// Decrement count
else if (s[i] == 'c')
count--;
// Query the segment tree to
// find the sum of all values
// less than count
int val = query(0, n + count,
segTree, 2 * n);
ans += val;
// Update the current value of
// count in the segment tree
update(n + count, segTree, 2 * n);
}
// Print the answer
cout << ans;
}
// Driver Code
int main()
{
string S = "abccaab";
countSubstrings(S);
return 0;
}
输出:
11
时间复杂度: O(N*log N)
辅助空间: O(N)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live