janardan_sharma's blog

By janardan_sharma, history, 4 months ago, In English

could anyone please help me out with an approach for this question which came in an hackathon by cisco for SWE interns.

String Wars

In this question you are given an integer n and you have to construct a string of length n using only two uppercase letters A and B and there is a condition that you cannot use two B's adjacent to each other in the constructed string and the string should be mth lexicographically smallest string. if the mth string is not possible then print -1.

Given : 1 <= n <= 90 1 <= m <= 10^19

Testcase 1: n = 2 m = 3 answer : "BA"

Testcase 2: n = 2 m = 4 answer : "-1" , as only 3 distinct strings can be constructed --> "AA", "AB", "BA".

 
 
 
 
  • Vote: I like it
  • -2
  • Vote: I do not like it

»
4 months ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like it

Should this work? Base 2 encoding: A is bit 1 B is bit 0

So
AA is 11
AB is 10
BA is 01
counting backwards
AAA is 111
AAB is 110
ABA is 101
....

  • »
    »
    4 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    How do you take care of the consecutive B's condition?

  • »
    »
    4 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    can you define some algo for string construction as the value of m is quite large so we cannot iterate over it.

»
4 months ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like it

deleted

»
4 months ago, # |
Rev. 3   Vote: I like it 0 Vote: I do not like it

Thinking this, didn't tried the implementation yet: T(n) = T(n — 1) (strings starting with A) + T(n — 2) (strings starting with BA)
Now fix A see if T(n — 1) is below m then fix A and go for next characters
else fix BA and go for T(n — 2) in same way

  • »
    »
    4 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it
    private static String solve(int n, int m) {
        char[] ans = new char[n + 1];
        int[] dp = new int[n + 1];
        dp[1] = 2;
        dp[2] = 3;
        for (int i = 3; i <= n; i++) {
           dp[i] = dp[i - 1] + dp[i - 2];
        }
        if (dp[n] < m) return "-1";
        long cnt = 0;
        int currentCharacter = n;
        while (currentCharacter >= 2) {
           if (cnt + dp[currentCharacter - 1] >= m) {
             ans[currentCharacter--] = 'A';
           } else {
             cnt += currentCharacter - 2 < 0 ? 0 : dp[currentCharacter - 1];
             ans[currentCharacter--] = 'B';
             ans[currentCharacter--] = 'A';
           }
        }
        if (currentCharacter == 1) {
           if (cnt + 1 == m) {
             ans[currentCharacter] = 'A';
           } else if (cnt + 2 == m) {
             ans[currentCharacter] = 'B';
           }
        }
        StringBuilder builder = new StringBuilder(new String(ans));
        return builder.reverse().toString();
    }
»
4 months ago, # |
Rev. 7   Vote: I like it 0 Vote: I do not like it
My attempt

An important thing to understand is how should we construct the answer when going from n to n - 1 (see the code). I thank charan2628 for the insights!

UPD: thanks forcdc, I have edited the comment.

  • »
    »
    4 months ago, # ^ |
      Vote: I like it +1 Vote: I do not like it

    I think there is a bug, your dp[1][0] is 2, you should initialize dp[1] and then start the loop from i=2, rest looks fine.