Skip to content
Related Articles

Related Articles

Improve Article

Number of ways of choosing K equal substrings of any length for every query

  • Last Updated : 03 Aug, 2021

Given a string str and Q queries. Each query consists of an integer K. The task is to find the number of ways of choosing K equal sub-strings of any length possible for every query. Note that the set of K substrings must be unique.
Examples: 
 

Input: str = “aabaab”, que[] = {3} 
Output:
“a” is the only sub-string that appears more than 3 times i.e. 4. 
And there are 4 ways of choosing 3 different strings from the given 4 strings.
Input: str = “aggghh”, que[] = {1, 2, 3} 
Output: 
21 


 

 

Approach: The following steps can be followed to solve the problem and answer every query in the minimal possible time. 
 

  • Generate all the substrings for a string and count the occurrence of every unique substring using hashing.
  • For every query, the answer will to choose K substrings of every string which occurs for more than K times(say X). The answer will be X \choose K
  • The time complexity per query can be reduced by pre-computing the binomial co-efficient

Below is the implementation of the above approach: 
 



C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
#define maxlen 100
 
// Function to generate all the sub-strings
void generateSubStrings(string s, unordered_map<string,
                                                int>& mpp)
{
 
    // Length of the string
    int l = s.length();
 
    // Generate all sub-strings
    for (int i = 0; i < l; i++) {
        string temp = "";
        for (int j = i; j < l; j++) {
            temp += s[j];
 
            // Count the occurrence of
            // every sub-string
            mpp[temp] += 1;
        }
    }
}
 
// Compute the Binomial Coefficient
void binomialCoeff(int C[maxlen][maxlen])
{
    int i, j;
 
    // Calculate value of Binomial Coefficient
    // in bottom up manner
    for (i = 0; i < 100; i++) {
        for (j = 0; j < 100; j++) {
 
            // Base Cases
            if (j == 0 || j == i)
                C[i][j] = 1;
 
            // Calculate value using previously
            // stored values
            else
                C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
        }
    }
}
 
// Function to return the result for a query
int answerQuery(unordered_map<string, int>& mpp,
                int C[maxlen][maxlen], int k)
{
    int ans = 0;
 
    // Iterate for every
    // unique sub-string
    for (auto it : mpp) {
 
        // Count the combinations
        if (it.second >= k)
            ans += C[it.second][k];
    }
 
    return ans;
}
 
// Driver code
int main()
{
    string s = "aabaab";
 
    // Get all the sub-strings
    // Store the occurrence of
    // all the sub-strings
    unordered_map<string, int> mpp;
    generateSubStrings(s, mpp);
 
    // Pre-computation
    int C[maxlen][maxlen];
    memset(C, 0, sizeof C);
    binomialCoeff(C);
 
    // Queries
    int queries[] = { 2, 3, 4 };
    int q = sizeof(queries) / sizeof(queries[0]);
 
    // Perform queries
    for (int i = 0; i < q; i++)
        cout << answerQuery(mpp, C, queries[i]) << endl;
 
    return 0;
}

Java




// Java implementation of the approach
import java.util.HashMap;
 
class GFG
{
    static int maxlen = 100;
 
    // Function to generate all the sub-strings
    public static void generateSubStrings(
                       String s, HashMap<String,
                                         Integer> mpp)
    {
 
        // Length of the string
        int l = s.length();
 
        // Generate all sub-strings
        for (int i = 0; i < l; i++)
        {
            String temp = "";
            for (int j = i; j < l; j++)
            {
                temp += s.charAt(j);
 
                // Count the occurrence of
                // every sub-string
                if (mpp.containsKey(temp))
                {
                    int x = mpp.get(temp);
                    mpp.put(temp, ++x);
                }
                else
                    mpp.put(temp, 1);
            }
        }
    }
 
    // Compute the Binomial Coefficient
    public static void binomialCoeff(int[][] C)
    {
        int i, j;
 
        // Calculate value of Binomial Coefficient
        // in bottom up manner
        for (i = 1; i < 100; i++)
        {
            for (j = 0; j < 100; j++)
            {
 
                // Base Cases
                if (j == 0 || j == i)
                    C[i][j] = 1;
 
                // Calculate value using previously
                // stored values
                else
                    C[i][j] = C[i - 1][j - 1] +
                              C[i - 1][j];
            }
        }
    }
 
    // Function to return the result for a query
    public static int answerQuery(HashMap<String,
                                          Integer> mpp,
                                      int[][] C, int k)
    {
        int ans = 0;
 
        // Iterate for every
        // unique sub-string
        for (HashMap.Entry<String,
                           Integer> entry : mpp.entrySet())
        {
 
            // Count the combinations
            if (entry.getValue() >= k)
                ans += C[entry.getValue()][k];
        }
        return ans;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        String s = "aabaab";
 
        // Get all the sub-strings
        // Store the occurrence of
        // all the sub-strings
        HashMap<String,
                Integer> mpp = new HashMap<>();
        generateSubStrings(s, mpp);
 
        // Pre-computation
        int[][] C = new int[maxlen][maxlen];
        binomialCoeff(C);
 
        // Queries
        int[] queries = { 2, 3, 4 };
        int q = queries.length;
 
        // Perform queries
        for (int i = 0; i < q; i++)
            System.out.println(answerQuery(mpp, C,
                                     queries[i]));
    }
}
 
// This code is contributed by
// sanjeev2552

Python3




# Python3 implementation of the approach
from collections import defaultdict
 
maxlen = 100
 
# Function to generate all the sub-strings
def generateSubStrings(s, mpp):
 
    # Length of the string
    l = len(s)
 
    # Generate all sub-strings
    for i in range(0, l):
        temp = ""
        for j in range(i, l):
            temp += s[j]
 
            # Count the occurrence of
            # every sub-string
            mpp[temp] += 1
 
# Compute the Binomial Coefficient
def binomialCoeff(C):
 
    # Calculate value of Binomial
    # Coefficient in bottom up manner
    for i in range(0, 100):
        for j in range(0, 100):
 
            # Base Cases
            if j == 0 or j == i:
                C[i][j] = 1
 
            # Calculate value using previously
            # stored values
            else:
                C[i][j] = C[i - 1][j - 1] + C[i - 1][j]
 
# Function to return the result for a query
def answerQuery(mpp, C, k):
 
    ans = 0
    # Iterate for every
    # unique sub-string
    for it in mpp:
 
        # Count the combinations
        if mpp[it] >= k:
            ans += C[mpp[it]][k]
 
    return ans
 
# Driver code
if __name__ == "__main__":
     
    s = "aabaab"
     
    # Get all the sub-strings
    # Store the occurrence of
    # all the sub-strings
    mpp = defaultdict(lambda:0)
    generateSubStrings(s, mpp)
 
    # Pre-computation
    C = [[0 for i in range(maxlen)]
            for j in range(maxlen)]
    binomialCoeff(C)
 
    # Queries
    queries = [2, 3, 4]
    q = len(queries)
 
    # Perform queries
    for i in range(0, q):
        print(answerQuery(mpp, C, queries[i]))
         
# This code is contributed by Rituraj Jain

C#




// C# code to print level order
// traversal in sorted order
using System;
using System.Collections.Generic;
 
class GFG
{
    static int maxlen = 100;
 
    // Function to generate all the sub-strings
    public static void generateSubStrings(String s,
                               Dictionary<String, int> mpp)
    {
 
        // Length of the string
        int l = s.Length;
 
        // Generate all sub-strings
        for (int i = 0; i < l; i++)
        {
            String temp = "";
            for (int j = i; j < l; j++)
            {
                temp += s[j];
 
                // Count the occurrence of
                // every sub-string
                if (mpp.ContainsKey(temp))
                {
                    mpp[temp] = ++mpp[temp];
                }
                else
                    mpp.Add(temp, 1);
            }
        }
    }
 
    // Compute the Binomial Coefficient
    public static void binomialCoeff(int[,] C)
    {
        int i, j;
 
        // Calculate value of Binomial Coefficient
        // in bottom up manner
        for (i = 1; i < 100; i++)
        {
            for (j = 0; j < 100; j++)
            {
 
                // Base Cases
                if (j == 0 || j == i)
                    C[i, j] = 1;
 
                // Calculate value using previously
                // stored values
                else
                    C[i, j] = C[i - 1, j - 1] +
                              C[i - 1, j];
            }
        }
    }
 
    // Function to return the result for a query
    public static int answerQuery(Dictionary<String, int> mpp,
                                           int[,] C, int k)
    {
        int ans = 0;
 
        // Iterate for every
        // unique sub-string
        foreach(KeyValuePair<String, int> entry in mpp)
        {
 
            // Count the combinations
            if (entry.Value >= k)
                ans += C[entry.Value, k];
        }
        return ans;
    }
 
    // Driver code
    public static void Main(String[] args)
    {
        String s = "aabaab";
 
        // Get all the sub-strings
        // Store the occurrence of
        // all the sub-strings
        Dictionary<String,
                   int> mpp = new Dictionary<String,   
                                             int>();
        generateSubStrings(s, mpp);
 
        // Pre-computation
        int[,] C = new int[maxlen, maxlen];
        binomialCoeff(C);
 
        // Queries
        int[] queries = { 2, 3, 4 };
        int q = queries.Length;
 
        // Perform queries
        for (int i = 0; i < q; i++)
            Console.WriteLine(answerQuery(mpp, C,
                                    queries[i]));
    }
}
 
// This code is contributed by 29AjayKumar

Javascript




<script>
 
// JavaScript implementation of the approach
 
let maxlen = 100;
 
// Function to generate all the sub-strings
function generateSubStrings(s,mpp)
{
    // Length of the string
        let l = s.length;
   
        // Generate all sub-strings
        for (let i = 0; i < l; i++)
        {
            let temp = "";
            for (let j = i; j < l; j++)
            {
                temp += s[j];
   
                // Count the occurrence of
                // every sub-string
                if (mpp.has(temp))
                {
                    let x = mpp.get(temp);
                    mpp.set(temp, ++x);
                }
                else
                    mpp.set(temp, 1);
            }
        }
}
 
// Compute the Binomial Coefficient
function binomialCoeff(C)
{
    let i, j;
   
        // Calculate value of Binomial Coefficient
        // in bottom up manner
        for (i = 1; i < 100; i++)
        {
            for (j = 0; j < 100; j++)
            {
   
                // Base Cases
                if (j == 0 || j == i)
                    C[i][j] = 1;
   
                // Calculate value using previously
                // stored values
                else
                    C[i][j] = C[i - 1][j - 1] +
                              C[i - 1][j];
            }
        }
}
 
// Function to return the result for a query
function answerQuery(mpp,C,k)
{
    let ans = 0;
   
        // Iterate for every
        // unique sub-string
        for (let[key,value] of mpp.entries())
        {
   
            // Count the combinations
            if (value >= k)
                ans += C[value][k];
        }
        return ans;
}
 
// Driver code
let s = "aabaab";
 
// Get all the sub-strings
// Store the occurrence of
// all the sub-strings
let mpp = new Map();
generateSubStrings(s, mpp);
 
// Pre-computation
let C = new Array(maxlen);
for(let i=0;i<maxlen;i++)
{
    C[i]=new Array(maxlen);
    for(let j=0;j<maxlen;j++)
        C[i][j]=0;
}
binomialCoeff(C);
 
// Queries
let queries = [ 2, 3, 4 ];
let q = queries.length;
 
// Perform queries
for (let i = 0; i < q; i++)
    document.write(answerQuery(mpp, C,
                               queries[i])+"<br>");
 
 
// This code is contributed by rag2127
 
</script>
Output: 
10
4
1

 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :