Lior and Jeffrey's answers form the foundation for solving the problem, but one interesting problem that remains to be solved in this post is, how can you efficiently compute the number of strings which are periodic for a given [input string, N, K]
. My answer will primarily focus on that.
As pointed out by Lior and Jeffrey, we need only to care about the substrings of length equal to the divisors of n when checking for strings which are periodic. Let's look at an example to see how efficient we can achieve this.
Number of periodic strings with period m
Let the input string be
0110 0011 0101 0001
and let us try to find the number of periodic strings with period m=4
First Bit
If we compare the first bit of each of the substrings, we'll see that all of them are 0
s. If we assume all the subsequent bits are the same, amongst all the substrings, then the input string can be made periodic (with period 4), when performing either 0 bitflips or 4 bitflips.
0110 0011 0101 0001
^ ^ ^ ^
Number of 0s = 4
Number of 1s = 0
Number of bitflips to make all 0s to 1s = 4
Number of bitflips to make all 1s to 0s = 0
Number of periodic strings with period=4 for:
k = 0 => 1
k = 4 => 1
So now we know there exists 2 strings which are periodic, one for k=0 and other for k=4 (assuming that the subsequent bits are the same in all the substrings).
Second Bit
Now let's progress to the second bit.
0110 0011 0101 0001
^ ^ ^ ^
Number of 0s = 2
Number of 1s = 2
Number of bitflips to make all 0s to 1s = 2
Number of bitflips to make all 1s to 0s = 2
But wait, the above statement is true IFF all the bits prior to the current bit in the substring also contribute in making the string periodic. We know that only k=0
and k=4
, each make the string periodic up to 1st bit.
So when accounting for all bits upto the 2nd bit, we can get a periodic string in the following 4 cases:
When previousK = 0:
Flip the 2 `0`s to `1`s => new k = 2
Flip the 2 `1`s to `0`s => new k = 2
When previousK = 4:
Flip the 2 `0`s to `1`s => new k = 6
Flip the 2 `1`s to `0`s => new k = 6
Number of periodic strings with period=4 for:
k = 2 => 2
k = 6 => 2
Third Bit
Moving on to third bit, we'll see this:
0110 0011 0101 0001
^ ^ ^ ^
Number of 0s = 2
Number of 1s = 2
Number of bitflips to make all 0s to 1s = 2
Number of bitflips to make all 1s to 0s = 2
We can get a periodic string in the following 4 cases:
When previousK = 2:
Flip the 2 `0`s to `1`s => new k = 4
Flip the 2 `1`s to `0`s => new k = 4
When previousK = 6:
Flip the 2 `0`s to `1`s => new k = 8
Flip the 2 `1`s to `0`s => new k = 8
Number of periodic strings with period=4 for:
k = 4 => 4
k = 8 => 4
Fourth Bit
For our fourth and final bit:
0110 0011 0101 0001
^ ^ ^ ^
Number of 0s = 1
Number of 1s = 3
We can get a periodic string in the following 4 cases:
When previousK = 4:
Flip the 1 `0`s to `1`s => new k = 5
Flip the 3 `1`s to `0`s => new k = 7
When previousK = 8:
Flip the 1 `0`s to `1`s => new k = 9
Flip the 3 `1`s to `0`s => new k = 11
Number of periodic strings with period=4 for:
k = 5 => 4
k = 7 => 4
k = 9 => 4
k = 11 => 4
We are now done with the last bit of the substring and the total of the periodic strings for various k values in the last step gives 16.
Recursive relation and Pseudocode
Let us denote the current count of periodic strings for any k
which varies from 1
to K
using R[k]. For each iteration, we need to look up the previous iteration's R[]
value.
What we essentially end up doing in each iteration is:
for offset = 0 to periodLen - 1
flip R[] and previousR[]
for currentK = 1 to K
R[currentK] = 0
numZeroes = 0
for (pos = offset; pos < n; pos += periodLen)
if (str[pos] == '0')
++numZeros
numOnes = (n / m) - numZeroes;
for currentK = 1 to K
if m == 0
R[currentK + numZeroes] = 1
R[currentK + numOnes] = 1
else if (previousR[currentK] > 0)
R[currrentK + numZeroes] += previousR[currentK]
R[currentK + numOnes] += previousR[currentK]
totalPeriodicCount = 0
for currentK = 1 to K
totalPeriodicCount += R[currentK]
If we perform the above process by iterating over all periods from the lowest to the highest we'll get the count of all the periodic strings. The periods which will be chosen will be the divisors of N
which are less than N
. Going over them from lowest to highest will have an advantage, read the next section for the details.
Accounting for periods which are divisible by smaller periods
On close observation you'll notice that we're also counting certain periodic strings more than once.
eg. the following periodic string:
0001 0001 0001 0001
will end up being counted as part of both m = 4, and m = 8
Let C[m]
denote the total count of periodic strings obtained for a period of length m
obtained using the above pseudocode. Let C[m']
denote the actual count of periodic strings obtained using period of length m
but not counting the periodic strings which can be formed using periods < m
More specifically, if the current period m
has divisors t
, u
and v
which are less than m
, then we'll be counting the number of periodic strings of periods t
, u
and v
as well, i.e.
C[m] = C[t'] + C[u'] + C[v'] + C[m']
When counting the total number of periodic strings for all values of m, we need to take care of excluding C[t]
, C[u]
, and C[v]
and only account for C[m']
.
Since when we're computing C[m]
, we already would have computed the values for C[t']
, C[u']
and C[v']
, we just need to look them up and subtract them from C[m]
to obtain C[m']
. I'll leave this simple portion as an exercise for the reader.
C[m'] = C[m] - C[t'] - C[u'] - C[v']