Open In App

Count Substrings with even frequency of each character and one exception

Last Updated : 24 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a string S (‘a’ ? S[i] ? ‘t’) of length N (1 ? N ? 105), which consists of lowercase English alphabets, the task is to count all substrings such that the frequency of all characters should be even or all characters should occur an even number of times except any one character which might occur an odd number of times.

Examples: 

Input: S = “aab”
Output: 5
Explanation: The five valid substrings are underlined below:
aab” -> “a”
“aab” -> “a”
aab” -> “aa”
“aab” -> “b”
aab” -> “aab”

Input: S = “abba”
Output: 8

An approach using Bitmasking:

The idea is to use Bitmasking technique, We’ll encode all visited character from 0 to ith index into our mask and add count of same mask that had occurred previously.

Follow the steps to implement the above idea:

  • Create an array dp[] of size 2m where m is the distinct character in the given string [because there is this much possibility for any character to occur till any index]. dp[i] will Store the count of valid substrings having mask i
  • Initialize dp[0] = 1, as there is one possible way of the valid substring having mask 0 (i.e, if we don’t consider any character from the string).
  • Iterate from i = 0 to N-1:
    • Calculate the current mask at (S[i] – ‘a’) index.
    • Add all the previous valid substrings that had the same mask
    • Iterate from j = 0 to 20 for the current mask:
      • Flip the jth bit of the current mask.
      • Add all previous valid substrings having the same mask
    • Increment the frequency of the current mask
  • Return the result

Below is the implementation of the above approach:

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// dp[i] will Store the count of valid
// substring having mask i
vector<int> dp;
 
// Function to count all the valid substring
long long allvalidString(string& word)
{
    dp.resize(1 << 20);
    long long mask = 0, result = 0;
 
    // One possible way for empty mask
    dp[0] = 1;
 
    for (auto ch : word) {
 
        // Toggle the bit of mask at
        // (ch - 'a') index.
        mask ^= 1 << (ch - 'a');
 
        // Add all previous valid substring
        // having same mask
        result += dp[mask];
 
        // Iterate for all english character
        // and toggle the corresponding bit.
        for (int i = 0; i < 20; i++) {
 
            // Add all the previous valid
            // substring that had same mask
            result += dp[mask ^ (1 << i)];
        }
 
        // Increment the frequency
        // of current mask
        dp[mask]++;
    }
 
    // Return the result
    return result;
}
 
// Driver code
int main()
{
    string s = "abba";
 
    // Function call
    cout << allvalidString(s);
 
    return 0;
}


Java




// Java code to implement the approach
import java.io.*;
 
class GFG
{
   
  // dp[i] will Store the count of valid
  // substring having mask i
  static int dp[] = new int[1 << 20];
 
  // Function to count all the valid substring
  public static long allvalidString(String word)
  {
    int mask = 0, result = 0;
 
    // One possible way for empty mask
    dp[0] = 1;
 
    for (int j = 0; j < word.length(); j++) {
      char ch = word.charAt(j);
       
      // Toggle the bit of mask at
      // (ch - 'a') index.
      mask ^= 1 << (ch - 'a');
 
      // Add all previous valid substring
      // having same mask
      result += dp[mask];
 
      // Iterate for all english character
      // and toggle the corresponding bit.
      for (int i = 0; i < 20; i++) {
 
        // Add all the previous valid
        // substring that had same mask
        result += dp[mask ^ (1 << i)];
      }
 
      // Increment the frequency
      // of current mask
      dp[mask]++;
    }
 
    // Return the result
    return result;
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    String s = "abba";
 
    // Function call
    System.out.print(allvalidString(s));
  }
}
 
// This code is contributed by Rohit Pradhan


Python3




# python3 code to implement the approach
 
# dp[i] will Store the count of valid
#  having mask i
dp = []
 
# Function to count all the valid substring
def allvalidString(word):
    global dp
    dp = [0 for _ in range(1 << 20)]
    mask = 0
    result = 0
 
    # One possible way for empty mask
    dp[0] = 1
 
    for ch in word:
 
        # Toggle the bit of mask at
        # (ch - 'a') index.
        mask ^= 1 << (ord(ch) - ord('a'))
 
        # Add all previous valid substring
        # having same mask
        result += dp[mask]
 
        # Iterate for all english character
        # and toggle the corresponding bit.
        for i in range(0, 20):
 
            # Add all the previous valid
            # substring that had same mask
            result += dp[mask ^ (1 << i)]
 
        # Increment the frequency
        # of current mask
        dp[mask] += 1
 
    # Return the result
    return result
 
# Driver code
if __name__ == "__main__":
 
    s = "abba"
 
    # Function call
    print(allvalidString(s))
 
    # This code is contributed by rakeshsahni


C#




// C# code to implement the approach
using System;
using System.Collections;
 
public class GFG {
  public static int allvalidString(string s)
  {
 
    int[] dp = new int[1 << 20];
    int mask = 0;
    int result = 0;
    dp[0] = 1;
 
    for (int i = 0; i < s.Length; i++) {
 
      // Toggle the bit of mask at
      // (ch - 'a') index.
      mask ^= 1 << (s[i] - 'a');
 
      // Add all previous valid substring
      // having same mask
      result += dp[mask];
 
      // Iterate for all english character
      // and toggle the corresponding bit.
      for (int j = 0; j < 20; j++) {
 
        // Add all the previous valid
        // substring that had same mask
        result += dp[mask ^ (1 << j)];
      }
 
      // Increment the frequency
      // of current mask
      dp[mask]++;
    }
 
    // Return the result
    return result;
  }
 
  public static void Main(string[] args)
  {
 
    string s = "abba";
 
    // Function call
    Console.WriteLine(allvalidString(s));
  }
}
 
// This code is contributed by garg28harsh.


Javascript




   // JavaScript code for the above approach
 
   // dp[i] will Store the count of valid
   // substring having mask i
   let dp = new Array(1 << 20).fill(0);
 
   // Function to count all the valid substring
   function allvalidString(word) {
 
     let mask = 0, result = 0;
 
     // One possible way for empty mask
     dp[0] = 1;
 
     for (let ch of word) {
 
       // Toggle the bit of mask at
       // (ch - 'a') index.
       mask ^= 1 << (ch.charCodeAt(0) - 'a'.charCodeAt(0));
 
       // Add all previous valid substring
       // having same mask
       result += dp[mask];
 
       // Iterate for all english character
       // and toggle the corresponding bit.
       for (let i = 0; i < 20; i++) {
 
         // Add all the previous valid
         // substring that had same mask
         result += dp[mask ^ (1 << i)];
       }
 
       // Increment the frequency
       // of current mask
       dp[mask]++;
     }
 
     // Return the result
     return result;
   }
 
   // Driver code
   let s = "abba";
 
   // Function call
   console.log(allvalidString(s));
 
// This code is contributed by Potta Lokesh


Output

8

Time Complexity: O(N), where n is the length of the given string
Auxiliary Space: O(2m), where m is the distinct character in the given string.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads