Lexicographically smallest permutation of a string with given subsequences

Given a string consisting only of two lowercase characters x and y and two numbers p and q. The task is to print the lexicographically smallest permutation of the given string such that the count of subsequences of xy is p and of yx is q. If no such string exists, print “Impossible” (without quotes).

Examples:

Input: str = "yxxyx", p = 3, q = 3 
Output: xyxyx

Input: str = "yxxy", p = 3, q = 2
Output: Impossible



Approach: First of all, by induction it can prove that the product of count of ‘x’ and count of ‘y’ should be equal to the sum of the count of a subsequence of ‘xy’ and ‘yx’ for any given string. If this does not hold then the answer is ‘Impossible’ else answer always exist.

Now, sort the given string so the count of a subsequence of ‘yx’ becomes zero. Let nx be the count of ‘x’ and ny be count of ‘y’. let a and b be the count of subsequence ‘xy’ and ‘yx’ respectively, then a = nx*ny and b = 0. Then, from beginning of the string find the ‘x’ which has next ‘y’ to it and swap both untill you reach end of the string. In each swap a is decremented by 1 and b is incremented by 1. Repeat this until the count of a subsequence of ‘yx’ is achieved i:e a becomes p and b becomes q.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// CPP program to find lexicographically smallest
// string such that count of subsequence 'xy' and
// 'yx' is p and q respectively.
#include <bits/stdc++.h>
using namespace std;
  
// function to check if answer exits
int nx = 0, ny = 0;
  
bool check(string s, int p, int q)
{
    // count total 'x' and 'y' in string
    for (int i = 0; i < s.length(); ++i) {
        if (s[i] == 'x')
            nx++;
        else
            ny++;
    }
  
    // condition to check existence of answer
    if (nx * ny != p + q)
        return 1;
    else
        return 0;
}
  
// function to find lexicographically smallest string
string smallestPermutation(string s, int p, int q)
{
    // check if answer exist or not
    if (check(s, p, q) == 1) {
        return "Impossible";
    }
  
    sort(s.begin(), s.end());
    int a = nx * ny, b = 0, i, j;
  
    // check if count of 'xy' and 'yx' becomes
    // equal to p and q respectively.
    if (a == p && b == q) {
        return s;
    }
  
    // Repeat until answer is found.
    while (1) {
        // Find index of 'x' to swap with 'y'.
        for (i = 0; i < s.length() - 1; ++i) {
            if (s[i] == 'x' && s[i + 1] == 'y')
                break;
        }
  
        for (j = i; j < s.length() - 1; j++) {
            if (s[j] == 'x' && s[j + 1] == 'y') {
                swap(s[j], s[j + 1]);
                a--; // 'xy' decrement by 1
                b++; // 'yx' increment by 1
  
                // check if count of 'xy' and 'yx' becomes
                // equal to p and q respectively.
                if (a == p && b == q) {
                    return s;
                }
            }
        }
    }
}
  
// Driver code
int main()
{
    string s = "yxxyx";
    int p = 3, q = 3;
  
    cout<< smallestPermutation(s, p, q);
      
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to find lexicographically 
// smallest string such that count of 
// subsequence 'xy' and 'yx' is p and 
// q respectively.
import java.util.*;
  
class GFG
{
static int nx = 0, ny = 0
      
static boolean check(String s, 
                     int p, int q) 
    // count total 'x' and 'y' in string 
    for (int i = 0; i < s.length(); ++i)
    
        if (s.charAt(i) == 'x'
            nx++; 
        else
            ny++; 
    
  
    // condition to check 
    // existence of answer 
    if ((nx * ny) != (p + q)) 
        return true
    else
        return false
  
public static String smallestPermutation(String s,
                                         int p, int q)
{
    if (check(s, p, q) == true
    
        return "Impossible"
    }
          
    char tempArray[] = s.toCharArray();
    Arrays.sort(tempArray);
      
    String str = new String(tempArray); 
    int a = nx * ny, b = 0, i = 0, j = 0;
          
    if (a == p && b == q) 
    
        return str; 
    }
      
    while (1 > 0
    
          
    // Find index of 'x' to swap with 'y'. 
    for (i = 0; i < str.length() - 1; ++i)
    
        if (str.charAt(i) == 'x' && 
            str.charAt(i + 1) == 'y'
            break
    
  
    for (j = i; j < str.length() - 1; j++) 
    
        if (str.charAt(j) == 'x' && 
            str.charAt(j + 1) == 'y'
        
        StringBuilder sb = new StringBuilder(str);
        sb.setCharAt(j, str.charAt(j + 1));
        sb.setCharAt(j + 1, str.charAt(j));
        str = sb.toString();
        /* char ch[] = str.toCharArray();
            char temp = ch[j+1];
            ch[j+1] = ch[j];
            ch[j] = temp;*/
              
            a--; // 'xy' decrement by 1 
            b++; // 'yx' increment by 1 
  
            // check if count of 'xy' and 
            // 'yx' becomes equal to p 
            // and q respectively. 
            if (a == p && b == q) 
            
                return str; 
            
        
    
}
}
  
// Driver Code
public static void main (String[] args) 
{
    String s = "yxxyx"
    int p = 3, q = 3;
      
    System.out.print(smallestPermutation(s, p, q));
}
}
  
// This code is contributed by Kirti_Mangal

chevron_right


Python3

# Python3 program to find lexicographically
# smallest string such that count of subsequence
# ‘xy’ and ‘yx’ is p and q respectively.

# Function to check if answer exits
def check(s, p, q):

global nx
global ny

# count total ‘x’ and ‘y’ in string
for i in range(0, len(s)):
if s[i] == ‘x’:
nx += 1
else:
ny += 1

# condition to check existence of answer
if nx * ny != p + q:
return 1
else:
return 0

# Function to find lexicographically
# smallest string
def smallestPermutation(s, p, q):

# check if answer exist or not
if check(s, p, q) == 1:
return “Impossible”

s = sorted(s)
a, b, i = nx * ny, 0, 0

# check if count of ‘xy’ and ‘yx’ becomes
# equal to p and q respectively.
if a == p and b == q:
return ” . join(s)

# Repeat until answer is found.
while True:

# Find index of ‘x’ to swap with ‘y’.
for i in range(0, len(s) – 1):
if s[i] == ‘x’ and s[i + 1] == ‘y’:
break

for j in range(i, len(s) – 1):
if s[j] == ‘x’ and s[j + 1] == ‘y’:

s[j], s[j + 1] = s[j + 1], s[j]
a -= 1 # ‘xy’ decrement by 1
b += 1 # ‘yx’ increment by 1

# check if count of ‘xy’ and ‘yx’ becomes
# equal to p and q respectively.
if a == p and b == q:
return ” . join(s)

# Driver code
if __name__ == “__main__”:

nx, ny = 0, 0
s = “yxxyx”
p, q = 3, 3

print(smallestPermutation(s, p, q))

# This code is contributed by Rituraj Jain

Output:

xyxyx

Time Complexity: O(N2)



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : Kirti_Mangal, rituraj_jain



Article Tags :
Practice Tags :


Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.