Open In App

Find the lexicographically smallest string by prepending characters

Two Players A and B are playing a game using a non-empty string S of length N having lowercase English Alphabets. The length of string S is even. Each player also has a string of their own, initially empty. In one move, a player takes either the first or the last character of the string S, removes it from S and prepends it (adds to the beginning) to their own string. The game ends when the string S becomes empty. The winner is the player with the lexicographically smaller string. If the players’ string are equal, then it’s a draw. The task is to determine the winner of the game or if the game ends in a draw.

Note: Player A starts the game.



Examples:

Input: S = “geek”
Output: A
Explanation: Player A can always manage to win:



  • Player A chooses ‘g’, then Player B chooses ‘e’, then Player A chooses ‘e’ and Player B chooses ‘k’. Final String of Player A = “eg” and final string of Player B = “ke”.
  • Player A chooses ‘g’ then Player B chooses ‘k’, then Player A chooses ‘e’ and Player B chooses ‘e’. Final String of Player A = “eg” and final string of Player B = “ek”.

In both the cases, Player A can always have a lexicographically smaller string, therefore Player A is the winner.

Input: S = “gffg”
Output: Draw
Explanation: It can be seen that the game will always end in a draw if both the player play optimally.

Approach: To solve the problem, follow the below idea:

The problem can be solved using Dynamic Programming. Maintain a 2D array dp[][], such that dp[l][r] stores the winner for substring S[l:r]. Declare a recursive function, say solve(l, r) which returns integers corresponding to the outcomes:

  • If the outcome is a draw, then return 0.
  • If the player A wins, then return 1.
  • If the player B wins, then return 2.

At any state(l, r), Player A will choose one character, say c and then Player B will choose another character, say d. Then, they both prepended the characters to their string and continued the game with the smaller string S. Now, if we want to calculate the outcome of state (l, r) from (l’, r’), then we can say that we append the letters c and d.

Let’s say the new state becomes (l’, r’). So, if the outcome of (l’, r’) is not a Draw, then the outcome will remain unchanged for state(l, r). Otherwise, if the outcome of state (l’, r’) is a draw, then the outcome depends on the characters c and d.

Explore all the cases, where the player A can start from the beginning as well as from the end. If at any end, Player A can guarantee the win then Player A can win, otherwise the game might end in a Draw or Player B winning the game.

The final answer will be at dp[0][N-1].

Step-by-step algorithm:

Below is the implementation of the algorithm:




#include <bits/stdc++.h>
using namespace std;
 
// method to find the winner of the game
// return 0 if there is a draw, 1 if A wins and 2 if B wins
int solve(string s, int l, int r, vector<vector<int> >& dp)
{
    if (r - l == 1) {
        if (s[l] == s[r])
            return 0;
        return 1;
    }
 
    if (dp[l][r] != -1) {
        return dp[l][r];
    }
 
    // A chooses the character at index l and B chooses the
    // character at index r
    int res1 = solve(s, l + 1, r - 1, dp);
    // If the result is a draw then the answer will be
    // decided by the characters at index l and r
    if (res1 == 0) {
        if (s[l] < s[r])
            res1 = 1;
        else if (s[l] > s[r])
            res1 = 2;
    }
 
    // A chooses the character at index l and B chooses the
    // character at index l + 1
    int res2 = solve(s, l + 2, r, dp);
    // If the result is a draw then the answer will be
    // decided by the characters at index l and l + 1
    if (res2 == 0) {
        if (s[l] < s[l + 1])
            res2 = 1;
        else if (s[l] > s[l + 1])
            res2 = 2;
    }
 
    // A chooses the character at index r and B chooses the
    // character at index l
    int res3 = solve(s, l + 1, r - 1, dp);
    // If the result is a draw then the answer will be
    // decided by the characters at index l and r
    if (res3 == 0) {
        if (s[l] > s[r])
            res3 = 1;
        else if (s[l] < s[r])
            res3 = 2;
    }
 
    // A chooses the character at index r and B chooses the
    // character at index r - 1
    int res4 = solve(s, l, r - 2, dp);
    // If the result is a draw then the answer will be
    // decided by the characters at index r and r - 1
    if (res4 == 0) {
        if (s[r - 1] > s[r])
            res4 = 1;
        else if (s[r - 1] < s[r])
            res4 = 2;
    }
 
    // Check if there is a way such that A can guarantee the
    // win
    if ((res1 == 1 && res2 == 1)
        || (res3 == 1 && res4 == 1)) {
        return dp[l][r] = 1;
    }
 
    // Check if there is no way for A to win
    if (res1 == 2 && res2 == 2 && res3 == 2 && res4 == 2) {
        return dp[l][r] = 2;
    }
 
    // Draw
    return dp[l][r] = 0;
}
 
int main()
{
    string s = "geek";
    int n = s.length();
    vector<vector<int> > dp(n, vector<int>(n, -1));
    int res = solve(s, 0, n - 1, dp);
    if (res == 0)
        cout << "Draw\n";
    else if (res == 1)
        cout << "A\n";
    else
        cout << "B\n";
 
    return 0;
}




import java.util.Arrays;
 
public class Main {
    // method to find the winner of the game
    // return 0 if there is a draw, 1 if A wins and 2 if B wins
    static int solve(String s, int l, int r, int[][] dp) {
        if (r - l == 1) {
            if (s.charAt(l) == s.charAt(r))
                return 0;
            return 1;
        }
 
        if (dp[l][r] != -1) {
            return dp[l][r];
        }
 
        // A chooses the character at index l and B chooses the
        // character at index r
        int res1 = solve(s, l + 1, r - 1, dp);
        // If the result is a draw then the answer will be
        // decided by the characters at index l and r
        if (res1 == 0) {
            if (s.charAt(l) < s.charAt(r))
                res1 = 1;
            else if (s.charAt(l) > s.charAt(r))
                res1 = 2;
        }
 
        // A chooses the character at index l and B chooses the
        // character at index l + 1
        int res2 = solve(s, l + 2, r, dp);
        // If the result is a draw then the answer will be
        // decided by the characters at index l and l + 1
        if (res2 == 0) {
            if (s.charAt(l) < s.charAt(l + 1))
                res2 = 1;
            else if (s.charAt(l) > s.charAt(l + 1))
                res2 = 2;
        }
 
        // A chooses the character at index r and B chooses the
        // character at index l
        int res3 = solve(s, l + 1, r - 1, dp);
        // If the result is a draw then the answer will be
        // decided by the characters at index l and r
        if (res3 == 0) {
            if (s.charAt(l) > s.charAt(r))
                res3 = 1;
            else if (s.charAt(l) < s.charAt(r))
                res3 = 2;
        }
 
        // A chooses the character at index r and B chooses the
        // character at index r - 1
        int res4 = solve(s, l, r - 2, dp);
        // If the result is a draw then the answer will be
        // decided by the characters at index r and r - 1
        if (res4 == 0) {
            if (s.charAt(r - 1) > s.charAt(r))
                res4 = 1;
            else if (s.charAt(r - 1) < s.charAt(r))
                res4 = 2;
        }
 
        // Check if there is a way such that A can guarantee the
        // win
        if ((res1 == 1 && res2 == 1) || (res3 == 1 && res4 == 1)) {
            return dp[l][r] = 1;
        }
 
        // Check if there is no way for A to win
        if (res1 == 2 && res2 == 2 && res3 == 2 && res4 == 2) {
            return dp[l][r] = 2;
        }
 
        // Draw
        return dp[l][r] = 0;
    }
 
    public static void main(String[] args) {
        String s = "geek";
        int n = s.length();
        int[][] dp = new int[n][n];
        for (int[] row : dp) {
            Arrays.fill(row, -1);
        }
        int res = solve(s, 0, n - 1, dp);
        if (res == 0)
            System.out.println("Draw");
        else if (res == 1)
            System.out.println("A");
        else
            System.out.println("B");
    }
}
 
// This code is contributed by akshitaguprzj3




using System;
using System.Collections.Generic;
 
class Program {
    // Method to find the winner of the game
    // Returns 0 if there is a draw, 1 if A wins, and 2 if B
    // wins
    static int Solve(string s, int l, int r,
                     List<List<int> > dp)
    {
        if (r - l == 1) {
            if (s[l] == s[r])
                return 0;
            return 1;
        }
 
        if (dp[l][r] != -1) {
            return dp[l][r];
        }
 
        // A chooses the character at index l and B chooses
        // the character at index r
        int res1 = Solve(s, l + 1, r - 1, dp);
        // If the result is a draw then the answer will be
        // decided by the characters at index l and r
        if (res1 == 0) {
            if (s[l] < s[r])
                res1 = 1;
            else if (s[l] > s[r])
                res1 = 2;
        }
 
        // A chooses the character at index l and B chooses
        // the character at index l + 1
        int res2 = Solve(s, l + 2, r, dp);
        // If the result is a draw then the answer will be
        // decided by the characters at index l and l + 1
        if (res2 == 0) {
            if (s[l] < s[l + 1])
                res2 = 1;
            else if (s[l] > s[l + 1])
                res2 = 2;
        }
 
        // A chooses the character at index r and B chooses
        // the character at index l
        int res3 = Solve(s, l + 1, r - 1, dp);
        // If the result is a draw then the answer will be
        // decided by the characters at index l and r
        if (res3 == 0) {
            if (s[l] > s[r])
                res3 = 1;
            else if (s[l] < s[r])
                res3 = 2;
        }
 
        // A chooses the character at index r and B chooses
        // the character at index r - 1
        int res4 = Solve(s, l, r - 2, dp);
        // If the result is a draw then the answer will be
        // decided by the characters at index r and r - 1
        if (res4 == 0) {
            if (s[r - 1] > s[r])
                res4 = 1;
            else if (s[r - 1] < s[r])
                res4 = 2;
        }
 
        // Check if there is a way such that A can guarantee
        // the win
        if ((res1 == 1 && res2 == 1)
            || (res3 == 1 && res4 == 1)) {
            return dp[l][r] = 1;
        }
 
        // Check if there is no way for A to win
        if (res1 == 2 && res2 == 2 && res3 == 2
            && res4 == 2) {
            return dp[l][r] = 2;
        }
 
        // Draw
        return dp[l][r] = 0;
    }
 
    static void Main(string[] args)
    {
        string s = "geek";
        int n = s.Length;
        List<List<int> > dp = new List<List<int> >();
        for (int i = 0; i < n; i++) {
            dp.Add(new List<int>());
            for (int j = 0; j < n; j++) {
                dp[i].Add(-1);
            }
        }
        int res = Solve(s, 0, n - 1, dp);
        if (res == 0)
            Console.WriteLine("Draw");
        else if (res == 1)
            Console.WriteLine("A");
        else
            Console.WriteLine("B");
    }
}




// Method to find the winner of the game
// Returns 0 if there is a draw, 1 if A wins, and 2 if B wins
function solve(s, l, r, dp) {
    if (r - l === 1) {
        if (s[l] === s[r])
            return 0;
        return 1;
    }
 
    if (dp[l][r] !== -1) {
        return dp[l][r];
    }
 
    // A chooses the character at index l and B chooses the
    // character at index r
    let res1 = solve(s, l + 1, r - 1, dp);
    // If the result is a draw then the answer will be
    // decided by the characters at index l and r
    if (res1 === 0) {
        if (s[l] < s[r])
            res1 = 1;
        else if (s[l] > s[r])
            res1 = 2;
    }
 
    // A chooses the character at index l and B chooses the
    // character at index l + 1
    let res2 = solve(s, l + 2, r, dp);
    // If the result is a draw then the answer will be
    // decided by the characters at index l and l + 1
    if (res2 === 0) {
        if (s[l] < s[l + 1])
            res2 = 1;
        else if (s[l] > s[l + 1])
            res2 = 2;
    }
 
    // A chooses the character at index r and B chooses the
    // character at index l
    let res3 = solve(s, l + 1, r - 1, dp);
    // If the result is a draw then the answer will be
    // decided by the characters at index l and r
    if (res3 === 0) {
        if (s[l] > s[r])
            res3 = 1;
        else if (s[l] < s[r])
            res3 = 2;
    }
 
    // A chooses the character at index r and B chooses the
    // character at index r - 1
    let res4 = solve(s, l, r - 2, dp);
    // If the result is a draw then the answer will be
    // decided by the characters at index r and r - 1
    if (res4 === 0) {
        if (s[r - 1] > s[r])
            res4 = 1;
        else if (s[r - 1] < s[r])
            res4 = 2;
    }
 
    // Check if there is a way such that A can guarantee the
    // win
    if ((res1 === 1 && res2 === 1)
        || (res3 === 1 && res4 === 1)) {
        return dp[l][r] = 1;
    }
 
    // Check if there is no way for A to win
    if (res1 === 2 && res2 === 2 && res3 === 2 && res4 === 2) {
        return dp[l][r] = 2;
    }
 
    // Draw
    return dp[l][r] = 0;
}
 
function main() {
    let s = "geek";
    let n = s.length;
    let dp = new Array(n).fill(null).map(() => new Array(n).fill(-1));
    let res = solve(s, 0, n - 1, dp);
    if (res === 0)
        console.log("Draw");
    else if (res === 1)
        console.log("A");
    else
        console.log("B");
}
 
main();




# Python Implementation
 
# method to find the winner of the game
# return 0 if there is a draw, 1 if A wins and 2 if B wins
def solve(s, l, r, dp):
    if r - l == 1:
        if s[l] == s[r]:
            return 0
        return 1
 
    if dp[l][r] != -1:
        return dp[l][r]
 
    # A chooses the character at index l and B chooses the
    # character at index r
    res1 = solve(s, l + 1, r - 1, dp)
    # If the result is a draw then the answer will be
    # decided by the characters at index l and r
    if res1 == 0:
        if s[l] < s[r]:
            res1 = 1
        elif s[l] > s[r]:
            res1 = 2
 
    # A chooses the character at index l and B chooses the
    # character at index l + 1
    res2 = solve(s, l + 2, r, dp)
    # If the result is a draw then the answer will be
    # decided by the characters at index l and l + 1
    if res2 == 0:
        if s[l] < s[l + 1]:
            res2 = 1
        elif s[l] > s[l + 1]:
            res2 = 2
 
    # A chooses the character at index r and B chooses the
    # character at index l
    res3 = solve(s, l + 1, r - 1, dp)
    # If the result is a draw then the answer will be
    # decided by the characters at index l and r
    if res3 == 0:
        if s[l] > s[r]:
            res3 = 1
        elif s[l] < s[r]:
            res3 = 2
 
    # A chooses the character at index r and B chooses the
    # character at index r - 1
    res4 = solve(s, l, r - 2, dp)
    # If the result is a draw then the answer will be
    # decided by the characters at index r and r - 1
    if res4 == 0:
        if s[r - 1] > s[r]:
            res4 = 1
        elif s[r - 1] < s[r]:
            res4 = 2
 
    # Check if there is a way such that A can guarantee the
    # win
    if (res1 == 1 and res2 == 1) or (res3 == 1 and res4 == 1):
        dp[l][r] = 1
        return 1
 
    # Check if there is no way for A to win
    if res1 == 2 and res2 == 2 and res3 == 2 and res4 == 2:
        dp[l][r] = 2
        return 2
 
    # Draw
    dp[l][r] = 0
    return 0
 
if __name__ == "__main__":
    s = "geek"
    n = len(s)
    dp = [[-1 for _ in range(n)] for _ in range(n)]
    res = solve(s, 0, n - 1, dp)
    if res == 0:
        print("Draw")
    elif res == 1:
        print("A")
    else:
        print("B")
 
 
# This code is contributed by Tapesh(tapeshdu420)

Output
A





Time Complexity: O(N * N), where N is the length of the input string S.
Auxiliary Space: O(N * N)


Article Tags :