Count even indices of String whose prefix has prime number of distinct Characters


In this problem, we will find total invalid characters in the given string. If total distinct characters till the particular even index is prime, we can say the character is invalid.

We can use the map data structure to count the total number of distinct characters while traversing the string. Also, we can use the string of characters to keep track of the distinct digits. Also, for every character, we can check whether its index is even and whether distinct characters are prime.

Problem statement – We have given a string alpha containing the N characters. We need to find the total invalid characters in the given string. The character is invalid if the total number of different characters is a prime number in the range [0, index], where 0 <= index < N and the index is even.

Sample Examples

Input

alpha = "ppqprs"

Output

2

Explanation

  • 2nd index is even, and the total distinct characters are 2, the prime number. So, 2nd index is invalid.

  • 4th index is also even, and the total distinct characters are 3, the prime number. So, 4th index is also invalid.

Input

alpha = "tttttt";

Output

0

Explanation

The total number of distinct characters is 1, as all characters of the strings are the same.

Input

alpha = "abcdefgh";

Output

3

Explanation

  • At the 2nd index, the total number of distinct characters is 3.

  • At the 4th index, the total number of distinct characters is 5.

  • At the 6th index, the total number of distinct characters is 7.

Approach 1

In this approach, we will find all prime numbers in the range 0 to 10,00,000. After that, we will use the map data structure to store the distinct characters. If, at any even index, the number of distinct characters is prime, we will count the index as an invalid index.

Algorithm

  • Step 1 − Execute the computePrimeNums() function to find all prime numbers in the range 0 to 10,00,000.

  • Step 1.2 − In the computePrimeNums() function, initialize the ‘primeNum’ array elements with 1, assuming all numbers are prime numbers initially.

  • Step 1.3 − We need to update the element from 1 to 0 if the number is not a prime number. So, update the element at the 0th and 1st index as they are not prime numbers.

  • Step 1.4 − At all even indexes, replace 1 with 0, as even numbers are not prime numbers.

  • Step 1.5 − Next, for each odd number, we need to check whether it is a prime number. So, start traversing the odd numbers.

  • Step 1.6 − Use another nested loop to traverse the odd numbers and replace the element at the p*q index, as it is not a prime number.

  • Step 2 − Initialize the ‘diffChars’ variable with 0 to store the total number of different characters till a particular index. Also, initialize the ‘cnt’ to store the count of the invalid characters. We will use the ‘freq’ map to store the frequency of characters.

  • Step 3 − Start iterating the string, and the frequency of the character in the map is 0, add the character to the map, and increment the ‘difChars’ by 1.

  • Step 4 − If p is divisible by 0, and ‘diffChars’ is a prime number, increment the value of the ‘cnt’ by 1.

  • Step 5 − Return the ‘cnt’ value.

Example

Following are the examples to the above algorithm −

#include <stdio.h>
#include <string.h>

// Array to store prime numbers
int primeNum[300];

// Function to calculate prime numbers
void computePrimeNums() {
   // Initialize array with 1
   memset(primeNum, 1, sizeof(primeNum));
   primeNum[0] = primeNum[1] = 0;
   
   // All even numbers are non-prime
   for (int p = 4; p <= 300; p += 2)
      primeNum[p] = 0;
   
   // For odd numbers
   for (int p = 3; p * p <= 300; p += 2) {
      if (primeNum[p]) {
         // Handling non-prime numbers
         for (int q = 3; q * p <= 300; q += 2)
            primeNum[p * q] = 0;
      }
   }
}

int getInvalidChars(int len, char* alpha) {
   computePrimeNums();
   int diffChars = 0;
   
   // To store final answer
   int cnt = 0;
   
   // For storing the frequency of characters
   int freq[256] = {0}; // Assuming ASCII characters
   
   // Traverse the string
   for (int p = 0; p < len; p++) {
      // If we got a character for the first time
      if (freq[alpha[p]] == 0) {
         freq[alpha[p]]++;
         diffChars++;
      }
      
      // For even index and diffChars is prime
      if ((p % 2 == 0) && primeNum[diffChars]) {
         cnt++;
      }
   }
   return cnt;
}
int main() {
   int len = 6;
   char alpha[] = "ppqprs";
   printf("The number of invalid characters is %d\n", getInvalidChars(len, alpha));
   return 0;
}

Output

The number of invalid characters is 2
#include <bits/stdc++.h>
using namespace std;

// Array to store prime numbers
int primeNum[300];
// Function to calculate prime numbers
void computePrimeNums() {

   // Initialize array with 1
   memset(primeNum, 1, sizeof primeNum);
   primeNum[0] = primeNum[1] = 0;
   
   // All even numbers are non-prime
   for (int p = 4; p <= 300; p += 2)
   primeNum[p] = 0;
   
   // For odd numbers
   for (int p = 3; p * p <= 300; p += 2) {
      if (primeNum[p]) {
      
         // Handling non-prime numbers
         for (int q = 3; q * p <= 300; q += 2)
         primeNum[p * q] = 0;
      }
   }
}
int getInvalidChars(int len, string alpha) {
   computePrimeNums();
   int diffChars = 0;
   
   // To store final answer
   int cnt = 0;
   
   // For storing the frequency of characters
   unordered_map<char, int> freq;
   
   // Traverse the string
   for (int p = 0; p < len; p++) {
   
      // If we got a character for the first time
      if (freq[alpha[p]] == 0) {
         freq[alpha[p]]++;
         diffChars++;
      }
      
      // For even index and diffChars is prime
      if (((p % 2) == 0) and primeNum[diffChars]) {
         cnt++;
      }
   }
   return cnt;
}
int main(){
   int len = 6;
   string alpha = "ppqprs";
   cout << "The number of invalid characters is " << getInvalidChars(len, alpha) << endl;
   return 0;
}

Output

The number of invalid characters is 2
import java.util.HashMap;

public class Main {
   // Array to store prime numbers
   static boolean[] primeNum = new boolean[301];

   // Function to calculate prime numbers
   static void computePrimeNums() {
      // Initialize array with true
      for (int i = 0; i < 301; i++) {
         primeNum[i] = true;
      }
      primeNum[0] = primeNum[1] = false;

      // All even numbers are non-prime
      for (int p = 4; p <= 300; p += 2) {
         primeNum[p] = false;
      }

      // For odd numbers
      for (int p = 3; p * p <= 300; p += 2) {
         if (primeNum[p]) {
            // Handling non-prime numbers
            for (int q = 3; q * p <= 300; q += 2) {
               primeNum[p * q] = false;
            }
         }
      }
   }

   static int getInvalidChars(String alpha) {
      computePrimeNums();
      int diffChars = 0;
      int cnt = 0;
      HashMap<Character, Integer> freq = new HashMap<>();

      // Traverse the string
      for (int p = 0; p < alpha.length(); p++) {
         // If we got a character for the first time
         if (freq.getOrDefault(alpha.charAt(p), 0) == 0) {
            freq.put(alpha.charAt(p), 1);
            diffChars++;
         }

         // For even index and diffChars is prime
         if (p % 2 == 0 && primeNum[diffChars]) {
            cnt++;
         }
      }
      return cnt;
   }

   public static void main(String[] args) {
      String alpha = "ppqprs";
      System.out.println("The number of invalid characters is " + getInvalidChars(alpha));
   }
}

Output

The number of invalid characters is 2
import math

# Function to calculate prime numbers
def compute_prime_nums():
   prime_nums = [True] * 301
   prime_nums[0] = prime_nums[1] = False

   # All even numbers are non-prime
   for p in range(4, 301, 2):
      prime_nums[p] = False

   # For odd numbers
   p = 3
   while p * p <= 300:
      if prime_nums[p]:
         # Handling non-prime numbers
         for q in range(3, 301, 2):
            if p * q <= 300:
               prime_nums[p * q] = False
      p += 2

   return prime_nums

def get_invalid_chars(alpha):
   prime_nums = compute_prime_nums()
   diff_chars = 0
   cnt = 0
   freq = {}

   # Traverse the string
   for p in range(len(alpha)):
      # If we got a character for the first time
      if freq.get(alpha[p], 0) == 0:
         freq[alpha[p]] = 1
         diff_chars += 1

      # For even index and diffChars is prime
      if p % 2 == 0 and prime_nums[diff_chars]:
         cnt += 1

   return cnt

def main():
   alpha = "ppqprs"
   print("The number of invalid characters is", get_invalid_chars(alpha))

if __name__ == "__main__":
   main()

Output

The number of invalid characters is 2

Time complexity − O(N + 300), as we traverse the string and calculate all prime numbers in the range of 300.

Space complexity − O(1) as we use constant space to store prime numbers.

Approach 2

In this approach, we will use the string to keep track of distinct characters. Also, we will check for prime numbers whenever we require rather than pre-calculating the prime numbers.

Algorithm

  • Step 1 − Initialize the ‘cnt’ with 0 and ‘diffChars’ with an empty string.

  • Step 2 − While traversing the string, check whether the character from the pth index of the string exists in the ‘diffCHars’ string using the find() method. If it doesn’t exist, append a character to the ‘diffChars’ string.

  • Step 3 − If the index is even, and the length of the ‘diffChars’ string is prime, increment the ‘cnt’ value by 1.

  • Step 3.1 − In the checkForPrime() function, return false if the number is less than or equal to 1.

  • Step 3.2 − Otherwise, make iterations until index*index is less than the number value.

  • Step 3.3 − In the loop, if the number is divisible by the index value, return false.

  • Step 3.4 − At last, return true.

  • Step 4 − At last, return the ‘cnt’ value.

Example

Following are the examples to the above algorithm −

#include <stdio.h>
#include <stdbool.h>
#include <string.h>

// Function to check if a number is prime
bool checkForPrime(int num) {
   if (num <= 1) {
      return false;
   }
   for (int p = 2; p * p <= num; p++) {
      if (num % p == 0) {
         return false; // not a prime number
      }
   }
   
   // Number is a prime number
   return true;
}

int getInvalidChars(int len, char alpha[]) {
   // To store final answer
   int cnt = 0;
   char diffChars[256] = {0}; // Assuming ASCII characters
   
   // Traverse the string
   for (int p = 0; p < len; p++) {
      // If we got a character for the first time
      if (strchr(diffChars, alpha[p]) == NULL) {
         diffChars[strlen(diffChars)] = alpha[p];
      }
      
      // For even index and diffChars is prime
      if ((p % 2 == 0) && checkForPrime(strlen(diffChars))) {
         cnt++;
      }
   }
   return cnt;
}
int main() {
   int len = 6;
   char alpha[] = "ppqprs";
   printf("The number of invalid characters is %d\n", getInvalidChars(len, alpha));
   return 0;
}

Output

The number of invalid characters is 2
#include <bits/stdc++.h>
using namespace std;

bool checkForPrime(int num) {
   if (num <= 1) {
      return false;
   }
   for (int p = 2; p * p <= num; p++) {
      if (num % p == 0) {
         return false; // not a prime number
      }
   }
   
   // Number is a prime number
   return true;
}
int getInvalidChars(int len, string alpha) {

   // To store final answer
   int cnt = 0;
   string diffChars = "";
   
   // Traverse the string
   for (int p = 0; p < len; p++) {
   
      // If we got a character for the first time
      if (diffChars.find(alpha[p]) == string::npos) {
         diffChars += alpha[p];
      }
      
      // For even index and diffChars is prime
      if (((p % 2) == 0) and checkForPrime(diffChars.length())) {
         cnt++;
      }
   }
   return cnt;
}
int main() {
   int len = 6;
   string alpha = "ppqprs";
   cout << "The number of invalid characters is " << getInvalidChars(len, alpha) << endl;
   return 0;
}

Output

The number of invalid characters is 2
public class Main {
   // Function to check if a number is prime
   static boolean checkForPrime(int num) {
      if (num <= 1) {
         return false;
      }
      for (int p = 2; p * p <= num; p++) {
         if (num % p == 0) {
            return false; // not a prime number
         }
      }
      
      // Number is a prime number
      return true;
   }

   static int getInvalidChars(String alpha) {
      // To store final answer
      int cnt = 0;
      StringBuilder diffChars = new StringBuilder();
      
      // Traverse the string
      for (int p = 0; p < alpha.length(); p++) {
         // If we got a character for the first time
         if (diffChars.indexOf(String.valueOf(alpha.charAt(p))) == -1) {
            diffChars.append(alpha.charAt(p));
         }
         
         // For even index and diffChars is prime
         if (p % 2 == 0 && checkForPrime(diffChars.length())) {
            cnt++;
         }
      }
      return cnt;
   }

   public static void main(String[] args) {
      String alpha = "ppqprs";
      System.out.println("The number of invalid characters is " + getInvalidChars(alpha));
   }
}

Output

The number of invalid characters is 2
# Function to check if a number is prime
def check_for_prime(num):
   if num <= 1:
      return False
   for p in range(2, int(num**0.5) + 1):
      if num % p == 0:
         return False  # not a prime number
   return True

def get_invalid_chars(alpha):
   # To store final answer
   cnt = 0
   diff_chars = ""
   
   # Traverse the string
   for p in range(len(alpha)):
      # If we got a character for the first time
      if alpha[p] not in diff_chars:
         diff_chars += alpha[p]
      
      # For even index and diffChars is prime
      if p % 2 == 0 and check_for_prime(len(diff_chars)):
         cnt += 1
   return cnt

def main():
   alpha = "ppqprs"
   print("The number of invalid characters is", get_invalid_chars(alpha))

if __name__ == "__main__":
   main()

Output

The number of invalid characters is 2

Time complexity − O(N*D), where N is a string length, and D is the total distinct characters in the given string.

Space complexity − O(1), as we don’t use any extra space.

We learned two different approaches to finding invalid characters in the given string. The first approach is very fast when given a large string containing millions of characters. The second approach is more space optimized as it doesn’t use any dynamic space.

Updated on: 16-Oct-2023

56 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements