Open In App

Count of N-length binary strings that are repeated concatenations of a substring

Last Updated : 07 May, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a positive integer N, the task is to find the number of binary strings of length N that are repeated concatenation of only one substring of that string.

Examples:

Input: N = 4
Output: 4
Explanation:
Below are the possible binary string of length N(= 4):

  1. “0000”: This string is the repeated concatenation of the substring “0”.
  2. “1111”: This string is the repeated concatenation of the substring “1”.
  3. “0101”: This string is the repeated concatenation of the substring “01”.
  4. “1010”: This string is the repeated concatenation of the substring “10”.

Therefore, the total count of such string is 4. Hence, print 4.

Input: N = 10
Output: 34

Approach: The given problem can be solved based on the observation that every possible string has a repeated substring which concatenated say K times, then the given length of string N must be divisible by K to generate all the resultant string.

Therefore, find all possible divisors of N and for each divisor, say K find the count of all possible strings it can form whose concatenation is the resultant string and this count can be calculated by 2K. Now, the number of strings that are repeated among them must also be subtracted, So perform the same operation on the divisor K and subtract it from 2K to get the total count for each recursive call.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include<bits/stdc++.h>
using namespace std;
 
// Store the recurring recursive states
map<int, int> dp;
 
// Function to find the number of
// strings of length N such that it
// is a concatenation it substrings
int countStrings(int N)
{
     
    // Single character cant be repeated
    if (N == 1)
        return 0;
     
    // Check if this state has been
    // already calculated
    if (dp.find(N) != dp.end())
        return dp[N];
     
    // Stores the resultant count for
    // the current recursive calls
    int ret = 0;
     
    // Iterate over all divisors
    for(int div = 1; div <= sqrt(N); div++)
    {
        if (N % div == 0)
        {
             
            // Non-Repeated = Total - Repeated
            ret += (1 << div) -  countStrings(div);
             
            int div2 = N/div;
             
            if (div2 != div and div != 1)
                 
                // Non-Repeated = Total - Repeated
                ret += (1 << div2) -  countStrings(div2);
        }
    }
     
    // Store the result for the
    // further calculation
    dp[N] = ret;       
                 
    // Return resultant count
    return ret;
}
 
// Driver code
int main()
{
    int N = 6;
     
    // Function Call
    cout << countStrings(N) << endl;
}
 
// This code is contributed by ipg2016107


Java




// Java program for the above approach
import java.util.*;
 
class GFG{
 
// Store the recurring recursive states
static HashMap<Integer,
               Integer> dp = new HashMap<Integer,
                                         Integer>();
 
// Function to find the number of
// strings of length N such that it
// is a concatenation it substrings
static int countStrings(int N)
{
     
    // Single character cant be repeated
    if (N == 1)
        return 0;
     
    // Check if this state has been
    // already calculated
    if (dp.containsKey(N))
        return dp.get(N);
     
    // Stores the resultant count for
    // the current recursive calls
    int ret = 0;
     
    // Iterate over all divisors
    for(int div = 1; div <= Math.sqrt(N); div++)
    {
        if (N % div == 0)
        {
             
            // Non-Repeated = Total - Repeated
            ret += (1 << div) -  countStrings(div);
             
            int div2 = N / div;
             
            if (div2 != div && div != 1)
                 
                // Non-Repeated = Total - Repeated
                ret += (1 << div2) -  countStrings(div2);
        }
    }
     
    // Store the result for the
    // further calculation
    dp.put(N, ret);       
                 
    // Return resultant count
    return ret;
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 6;
     
    // Function Call
    System.out.print(countStrings(N));
}
}
 
// This code is contributed by code_hunt


Python3




# Python program for the above approach
 
# Store the recurring recursive states
dp = {}
 
# Function to find the number of
# strings of length N such that it
# is a concatenation it substrings
def countStrings(N):
    
    # Single character cant be repeated
    if N == 1:
        return 0
     
    # Check if this state has been
    # already calculated
    if dp.get(N, -1) != -1:
        return dp[N]
     
    # Stores the resultant count for
    # the current recursive calls
    ret = 0
     
    # Iterate over all divisors
    for div in range(1, int(N**.5)+1): 
        if N % div == 0:
             
            # Non-Repeated = Total - Repeated
            ret += (1 << div) -  countStrings(div)
             
            div2 = N//div
             
            if div2 != div and div != 1:
                 
                # Non-Repeated = Total - Repeated
                ret += (1 << div2) -  countStrings(div2)
     
    # Store the result for the
    # further calculation
    dp[N] = ret         
                 
    # Return resultant count
    return ret
 
# Driver Code
N = 6
 
# Function Call
print(countStrings(N))


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
     
// Store the recurring recursive states
static Dictionary<int, int> dp = new Dictionary<int, int>();
 
// Function to find the number of
// strings of length N such that it
// is a concatenation it substrings
static int countStrings(int N)
{
     
    // Single character cant be repeated
    if (N == 1)
        return 0;
     
    // Check if this state has been
    // already calculated
    if (dp.ContainsKey(N))
        return dp[N];
     
    // Stores the resultant count for
    // the current recursive calls
    int ret = 0;
     
    // Iterate over all divisors
    for(int div = 1; div <= Math.Sqrt(N); div++)
    {
        if (N % div == 0)
        {
             
            // Non-Repeated = Total - Repeated
            ret += (1 << div) -  countStrings(div);
             
            int div2 = N / div;
             
            if (div2 != div && div != 1)
                 
                // Non-Repeated = Total - Repeated
                ret += (1 << div2) -  countStrings(div2);
        }
    }
     
    // Store the result for the
    // further calculation
    dp[N] = ret;     
                 
    // Return resultant count
    return ret;
}
 
// Driver Code
public static void Main()
{
    int N = 6;
     
    // Function Call
    Console.Write(countStrings(N));
}
}
 
// This code is contributed by splevel62.


Javascript




<script>
 
// JavaScript program for the above approach
 
// Store the recurring recursive states
let dp = new Map();
 
// Function to find the number of
// strings of length N such that it
// is a concatenation it substrings
function countStrings(N) {
  // Single character cant be repeated
  if (N == 1) return 0;
 
  // Check if this state has been
  // already calculated
  if (dp.has(N)) return dp.get(N);
 
  // Stores the resultant count for
  // the current recursive calls
  let ret = 0;
 
  // Iterate over all divisors
  for (let div = 1; div <= Math.sqrt(N); div++) {
    if (N % div == 0) {
      // Non-Repeated = Total - Repeated
      ret += (1 << div) - countStrings(div);
 
      let div2 = N / div;
 
      if (div2 != div && div != 1)
        // Non-Repeated = Total - Repeated
        ret += (1 << div2) - countStrings(div2);
    }
  }
 
  // Store the result for the
  // further calculation
  dp[N] = ret;
 
  // Return resultant count
  return ret;
}
 
// Driver code
 
let N = 6;
 
// Function Call
document.write(countStrings(N) + "<br>");
 
// This code is contributed by _saurabh_jaiswal
 
</script>


Output: 

10

 

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

Another approach : Using DP Tabulation method ( Iterative approach )

The approach to solve this problem is same but DP tabulation(bottom-up) method is better than Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.

Steps to solve this problem :

  • Create a DP of size N+1 to store the solution of the subproblems.
  • Initialize the DP  with base cases dp[0] = 1.
  • Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP
  • Return the final solution stored in dp[N]

Implementation :
 

C++




// C++ program for the above approach
#include<bits/stdc++.h>
using namespace std;
 
// Function to find the number of
// strings of length N such that it
// is a concatenation it substrings
int countStrings(int N)
{  
     
    // Single character cant be repeated
    if (N == 1)
        return 0;
     
    // initialize DP
    vector<int> dp(N+1);
     
    // Base case
    dp[1] = 0;
     
    // Iterate over subproblems to compute current
    // value from previous computations
    for (int i = 2; i <= N; i++) {
        int ret = 0;
        for(int div = 1; div <= sqrt(i); div++)
        {
            if (i % div == 0)
            {
                ret += (1 << div) - dp[div];
                 
                int div2 = i/div;
                 
                if (div2 != div and div != 1)
                    ret += (1 << div2) - dp[div2];
            }
        }
        // update dp
        dp[i] = ret;
    }
     
    // return final answer
    return dp[N];
}
 
// Driver code
int main()
{
    int N = 6;
     
    // Function Call
    cout << countStrings(N) << endl;
}
 
// this code is contributed by bhardwajji


Java




import java.util.*;
 
public class Main {
    // Function to find the number of
    // strings of length N such that it
    // is a concatenation it substrings
    static int countStrings(int N) {
        // Single character cant be repeated
        if (N == 1)
            return 0;
 
        // initialize DP
        int[] dp = new int[N + 1];
 
        // Base case
        dp[1] = 0;
 
        // Iterate over subproblems to compute current
        // value from previous computations
        for (int i = 2; i <= N; i++) {
            int ret = 0;
            for (int div = 1; div <= Math.sqrt(i); div++) {
                if (i % div == 0) {
                    ret += (1 << div) - dp[div];
 
                    int div2 = i / div;
 
                    if (div2 != div && div != 1)
                        ret += (1 << div2) - dp[div2];
                }
            }
            // update dp
            dp[i] = ret;
        }
 
        // return final answer
        return dp[N];
    }
 
    // Driver code
    public static void main(String[] args) {
        int N = 6;
 
        // Function Call
        System.out.println(countStrings(N));
    }
}
//This code is contributed by Akash Jha


Python




# Python program for the above approach
import math
 
# Function to find the number of
# strings of length N such that it
# is a concatenation it substrings
def countStrings(N):
     
    # Single character cant be repeated
    if N == 1:
        return 0
     
    # initialize DP
    dp = [0]*(N+1)
     
    # Base case
    dp[1] = 0
     
    # Iterate over subproblems to compute current
    # value from previous computations
    for i in range(2, N+1):
        ret = 0
        for div in range(1, int(math.sqrt(i))+1):
            if i % div == 0:
                ret += (1 << div) - dp[div]
                 
                div2 = i // div
                 
                if div2 != div and div != 1:
                    ret += (1 << div2) - dp[div2]
                     
        # update dp
        dp[i] = ret
     
    # return final answer
    return dp[N]
 
# Driver code
if __name__ == '__main__':
    N = 6
     
    # Function Call
    print(countStrings(N))


C#




using System;
 
public class Program
{
    // Function to find the number of
    // strings of length N such that it
    // is a concatenation it substrings
    static int CountStrings(int N)
    {
        // Single character cant be repeated
        if (N == 1)
            return 0;
 
        // initialize DP
        int[] dp = new int[N + 1];
 
        // Base case
        dp[1] = 0;
 
        // Iterate over subproblems to compute current
        // value from previous computations
        for (int i = 2; i <= N; i++)
        {
            int ret = 0;
            for (int div = 1; div <= Math.Sqrt(i); div++)
            {
                if (i % div == 0)
                {
                    ret += (1 << div) - dp[div];
 
                    int div2 = i / div;
 
                    if (div2 != div && div != 1)
                        ret += (1 << div2) - dp[div2];
                }
            }
            // update dp
            dp[i] = ret;
        }
 
        // return final answer
        return dp[N];
    }
 
    // Driver code
    public static void Main()
    {
        int N = 6;
 
        // Function Call
        Console.WriteLine(CountStrings(N));
    }
}
//This code is contributed by Akash Jha


Javascript




// Function to find the number of
// strings of length N such that it
// is a concatenation it substrings
function countStrings(N) {
  // Single character cant be repeated
  if (N == 1) {
    return 0;
  }
 
  // initialize DP
  let dp = new Array(N + 1);
 
  // Base case
  dp[1] = 0;
 
  // Iterate over subproblems to compute current
  // value from previous computations
  for (let i = 2; i <= N; i++) {
    let ret = 0;
    for (let div = 1; div <= Math.sqrt(i); div++) {
      if (i % div == 0) {
        ret += (1 << div) - dp[div];
 
        let div2 = i / div;
 
        if (div2 != div && div != 1) {
          ret += (1 << div2) - dp[div2];
        }
      }
    }
    // update dp
    dp[i] = ret;
  }
 
  // return final answer
  return dp[N];
}
 
// Driver code
let N = 6;
 
// Function Call
console.log(countStrings(N));


Output: 

10

 

Time Complexity: O(N * sqrt(N))
Auxiliary Space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads