Count of strings that can be formed using a, b and c under given constraints

Given a length n, count the number of strings of length n that can be made using ‘a’, ‘b’ and ‘c’ with at-most one ‘b’ and two ‘c’s allowed.

Examples:

Input : n = 3 
Output : 19 
Below strings follow given constraints:
aaa aab aac aba abc aca acb acc baa
bac bca bcc caa cab cac cba cbc cca ccb 

Input  : n = 4
Output : 39

Asked in Google Interview

A simple solution is to recursively count all possible combination of string that can be mode up to latter ‘a’, ‘b’, and ‘c’.

Below is C++ implementation of above idea

// C++ program to count number of strings
// of n characters with
#include<bits/stdc++.h>
using namespace std;

// n is total number of characters.
// bCount and cCount are counts of 'b'
// and 'c' respectively.
int countStr(int n, int bCount, int cCount)
{
    // Base cases
    if (bCount < 0 || cCount < 0) return 0;
    if (n == 0) return 1;
    if (bCount == 0 && cCount == 0) return 1;

    // Three cases, we choose, a or b or c
    // In all three cases n decreases by 1.
    int res = countStr(n-1, bCount, cCount);
    res += countStr(n-1, bCount-1, cCount);
    res += countStr(n-1, bCount, cCount-1);

    return res;
}

// Driver code
int main()
{
    int n = 3;  // Total number of characters
    cout << countStr(n, 1, 2);
    return 0;
}

Output:

19

Time complexity of above solution is exponential.

 

Efficient Solution
If we drown a recursion tree of above code, we can notice that same values appear multiple times. So we store results which are used later if repeated.

// C++ program to count number of strings
// of n characters with
#include<bits/stdc++.h>
using namespace std;

// n is total number of characters.
// bCount and cCount are counts of 'b'
// and 'c' respectively.
int countStrUtil(int dp[][2][3], int n, int bCount=1,
                 int cCount=2)
{
    // Base cases
    if (bCount < 0 || cCount < 0) return 0;
    if (n == 0) return 1;
    if (bCount == 0 && cCount == 0) return 1;

    // if we had saw this combination previously
    if (dp[n][bCount][cCount] != -1)
        return dp[n][bCount][cCount];

    // Three cases, we choose, a or b or c
    // In all three cases n decreases by 1.
    int res = countStrUtil(dp, n-1, bCount, cCount);
    res += countStrUtil(dp, n-1, bCount-1, cCount);
    res += countStrUtil(dp, n-1, bCount, cCount-1);

    return (dp[n][bCount][cCount] = res);
}

// A wrapper over countStrUtil()
int countStr(int n)
{
    int dp[n+1][2][3];
    memset(dp, -1, sizeof(dp));
    return countStrUtil(dp, n);
}

// Driver code
int main()
{
    int n = 3; // Total number of characters
    cout << countStr(n);
    return 0;
}

Output:

19

Time Complexity : O(n)
Auxiliary Space : O(n)

Thanks to Mr. Lazy for suggesting above solutions.

Reference :
https://careercup.appspot.com/question?id=5717453712654336

This article is contributed by Nishant Singh. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

GATE CS Corner    Company Wise Coding Practice





Writing code in comment? Please use ide.geeksforgeeks.org, generate link and share the link here.