Open In App

Count Substrings with even frequency of each character and one exception

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:

Below is the implementation of the above approach:




// 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 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 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# 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 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.


Article Tags :