Count of N-length binary strings that are repeated concatenations of a substring
Last Updated :
07 May, 2023
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):
- “0000”: This string is the repeated concatenation of the substring “0”.
- “1111”: This string is the repeated concatenation of the substring “1”.
- “0101”: This string is the repeated concatenation of the substring “01”.
- “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++
#include<bits/stdc++.h>
using namespace std;
map< int , int > dp;
int countStrings( int N)
{
if (N == 1)
return 0;
if (dp.find(N) != dp.end())
return dp[N];
int ret = 0;
for ( int div = 1; div <= sqrt (N); div ++)
{
if (N % div == 0)
{
ret += (1 << div ) - countStrings( div );
int div2 = N/ div ;
if (div2 != div and div != 1)
ret += (1 << div2) - countStrings(div2);
}
}
dp[N] = ret;
return ret;
}
int main()
{
int N = 6;
cout << countStrings(N) << endl;
}
|
Java
import java.util.*;
class GFG{
static HashMap<Integer,
Integer> dp = new HashMap<Integer,
Integer>();
static int countStrings( int N)
{
if (N == 1 )
return 0 ;
if (dp.containsKey(N))
return dp.get(N);
int ret = 0 ;
for ( int div = 1 ; div <= Math.sqrt(N); div++)
{
if (N % div == 0 )
{
ret += ( 1 << div) - countStrings(div);
int div2 = N / div;
if (div2 != div && div != 1 )
ret += ( 1 << div2) - countStrings(div2);
}
}
dp.put(N, ret);
return ret;
}
public static void main(String[] args)
{
int N = 6 ;
System.out.print(countStrings(N));
}
}
|
Python3
dp = {}
def countStrings(N):
if N = = 1 :
return 0
if dp.get(N, - 1 ) ! = - 1 :
return dp[N]
ret = 0
for div in range ( 1 , int (N * * . 5 ) + 1 ):
if N % div = = 0 :
ret + = ( 1 << div) - countStrings(div)
div2 = N / / div
if div2 ! = div and div ! = 1 :
ret + = ( 1 << div2) - countStrings(div2)
dp[N] = ret
return ret
N = 6
print (countStrings(N))
|
C#
using System;
using System.Collections.Generic;
class GFG{
static Dictionary< int , int > dp = new Dictionary< int , int >();
static int countStrings( int N)
{
if (N == 1)
return 0;
if (dp.ContainsKey(N))
return dp[N];
int ret = 0;
for ( int div = 1; div <= Math.Sqrt(N); div++)
{
if (N % div == 0)
{
ret += (1 << div) - countStrings(div);
int div2 = N / div;
if (div2 != div && div != 1)
ret += (1 << div2) - countStrings(div2);
}
}
dp[N] = ret;
return ret;
}
public static void Main()
{
int N = 6;
Console.Write(countStrings(N));
}
}
|
Javascript
<script>
let dp = new Map();
function countStrings(N) {
if (N == 1) return 0;
if (dp.has(N)) return dp.get(N);
let ret = 0;
for (let div = 1; div <= Math.sqrt(N); div++) {
if (N % div == 0) {
ret += (1 << div) - countStrings(div);
let div2 = N / div;
if (div2 != div && div != 1)
ret += (1 << div2) - countStrings(div2);
}
}
dp[N] = ret;
return ret;
}
let N = 6;
document.write(countStrings(N) + "<br>" );
</script>
|
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++
#include<bits/stdc++.h>
using namespace std;
int countStrings( int N)
{
if (N == 1)
return 0;
vector< int > dp(N+1);
dp[1] = 0;
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];
}
}
dp[i] = ret;
}
return dp[N];
}
int main()
{
int N = 6;
cout << countStrings(N) << endl;
}
|
Java
import java.util.*;
public class Main {
static int countStrings( int N) {
if (N == 1 )
return 0 ;
int [] dp = new int [N + 1 ];
dp[ 1 ] = 0 ;
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];
}
}
dp[i] = ret;
}
return dp[N];
}
public static void main(String[] args) {
int N = 6 ;
System.out.println(countStrings(N));
}
}
|
Python
import math
def countStrings(N):
if N = = 1 :
return 0
dp = [ 0 ] * (N + 1 )
dp[ 1 ] = 0
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]
dp[i] = ret
return dp[N]
if __name__ = = '__main__' :
N = 6
print (countStrings(N))
|
C#
using System;
public class Program
{
static int CountStrings( int N)
{
if (N == 1)
return 0;
int [] dp = new int [N + 1];
dp[1] = 0;
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];
}
}
dp[i] = ret;
}
return dp[N];
}
public static void Main()
{
int N = 6;
Console.WriteLine(CountStrings(N));
}
}
|
Javascript
function countStrings(N) {
if (N == 1) {
return 0;
}
let dp = new Array(N + 1);
dp[1] = 0;
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];
}
}
}
dp[i] = ret;
}
return dp[N];
}
let N = 6;
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
Please Login to comment...