Lexicographically smallest string with period K possible by replacing β€˜?’s from a given string

Given a string S consisting of N lowercase characters and character β€˜?’ and a positive integer K, the task is to replace each character β€˜?’ with some lowercase alphabets such that the given string becomes a period of K. If it is not possible to do so, then print β€œ-1”.

A string is said to be a period of K if and only if the length of the string is a multiple of K and for all possible value of i over the range [0, K) the value S[i + K], S[i + 2*K], S[i + 3*K], …, remains the same.

Examples:

Input: S = β€œab??”, K = 2
Output: abab

Input: S = β€œ??????”, K = 3
Output: aaaaaa

Naive Approach: The given approach can also be solved by generating all possible combination of strings by replacing each character β€˜?’ with any lowercase characters and print that string that have each substring of size K is the same.

Time Complexity: O(26M), where M is the number of β€˜?’ in the string S.
Auxiliary Space: O(1)

Efficient Approach: The above approach can also be optimized by traversing the string in a way such that the first, second, third, and so on characters are traversed and if all the characters are β€˜?’ then replace it with character β€˜a’, Otherwise, if there exists only one distinct character at each respective position then replace β€˜?’ with that character, Otherwise, the string can’t be modified as per the given criteria and hence, print β€œ-1”. Follow the steps below to solve the problem:

  • Iterate a loop over the range [0, K] using the variable i and perform the following steps:
    • Initialize a map, say M to store the frequency of characters of substring at positions i.
    • Traverse the given string over the range [i, N] using the variable j with an increment of K and store the frequency of the character S[j] by 1 in the map M.
    • After completing the above steps perform the following:
      • If the size of the map is greater than 2, then print β€œ-1” and break out of the loop.
      • Otherwise, if the size of the map is 2, then replace each β€˜?’ with that different character.
      • Otherwise, replace all the β€˜?’ with the character β€˜a’.
  • After completing the above steps, if the string can be modified, then print the string S as the result string.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include "bits/stdc++.h"
using namespace std;
 
// Function to modify the given string
// such that string S is a period of K
string modifyString(string& S, int K)
{
 
    int N = S.length();
 
    // Iterate over the range [0, K]
    for (int i = 0; i < K; i++) {
 
        // Stores the frequency of the
        // characters S[i + j*K]
        map<char, int> M;
 
        // Iterate over the string with
        // increment of K
        for (int j = i; j < N; j += K) {
            M[S[j]]++;
        }
 
        // Print "-1"
        if (M.size() > 2) {
            return "-1";
        }
        else if (M.size() == 1) {
            if (M['?'] != 0) {
 
                // Replace all characters
                // of the string with '?'
                // to 'a' to make it smallest
                for (int j = i; j < N; j += K) {
                    S[j] = 'a';
                }
            }
        }
 
        // Otherwise
        else if (M.size() == 2) {
            char ch;
 
            // Find the character other
            // than '?'
            for (auto& it : M) {
                if (it.first != '?') {
                    ch = it.first;
                }
            }
 
            // Replace all characters
            // of the string with '?'
            // to character ch
            for (int j = i; j < N; j += K) {
                S[j] = ch;
            }
        }
 
        // Clear the map M
        M.clear();
    }
 
    // Return the modified string
    return S;
}
 
// Driver Code
int main()
{
 
    string S = "ab??";
    int K = 2;
    cout << modifyString(S, K);
 
    return 0;
}


Java




// Java program for the above approach
import java.util.*;
 
class GFG{
 
  // Function to modify the given String
  // such that String S is a period of K
  static String modifyString(char[] S, int K)
  {
 
    int N = S.length;
 
    // Iterate over the range [0, K]
    for (int i = 0; i < K; i++) {
 
      // Stores the frequency of the
      // characters S[i + j*K]
      HashMap<Character,Integer> M = new HashMap<>();
 
      // Iterate over the String with
      // increment of K
      for (int j = i; j < N; j += K) {
 
        if(M.containsKey(S[j])){
          M.put(S[j], M.get(S[j])+1);
        }
        else{
          M.put(S[j], 1);
        }
      }
 
      // Print "-1"
      if (M.size() > 2) {
        return "-1";
      }
      else if (M.size() == 1) {
        if (M.get('?') != 0) {
 
          // Replace all characters
          // of the String with '?'
          // to 'a' to make it smallest
          for (int j = i; j < N; j += K) {
            S[j] = 'a';
          }
        }
      }
 
      // Otherwise
      else if (M.size() == 2) {
        char ch=' ';
 
        // Find the character other
        // than '?'
        for (Map.Entry<Character,Integer> entry : M.entrySet()) {
          if (entry.getKey() != '?') {
            ch = entry.getKey();
          }
        }
 
        // Replace all characters
        // of the String with '?'
        // to character ch
        for (int j = i; j < N; j += K) {
          S[j] = ch;
        }
      }
 
      // Clear the map M
      M.clear();
    }
 
    // Return the modified String
    return String.valueOf(S);
  }
 
  // Driver Code
  public static void main(String[] args)
  {
 
    String S = "ab??";
    int K = 2;
    System.out.print(modifyString(S.toCharArray(), K));
  }
}
 
// This code is contributed by umadevi9616


Python3




# python 3 program for the above approach
 
# Function to modify the given string
# such that string S is a period of K
def modifyString(S,K):
    N = len(S)
    S = list(S)
 
    # Iterate over the range [0, K]
    for i in range(K):
        # Stores the frequency of the
        # characters S[i + j*K]
        M = {}
 
        # Iterate over the string with
        # increment of K
        for j in range(i,N,K):
            if S[j] in M:
                M[S[j]] += 1
            else:
                M[S[j]] = 1
 
        # Print "-1"
        if (len(M) > 2):
            return "-1"
 
        elif (len(M) == 1):
            if (M['?'] != 0):
 
                # Replace all characters
                # of the string with '?'
                # to 'a' to make it smallest
                for j in range(i,N,K):
                    S[j] = 'a'
 
        # Otherwise
        elif(len(M) == 2):
            ch = ''
 
            # Find the character other
            # than '?'
            for key,value in M.items():
                if (key != '?'):
                    ch = key
            # Replace all characters
            # of the string with '?'
            # to character ch
            for j in range(i,N,K):
                S[j] = ch
 
        # Clear the map M
        M.clear()
    S = ''.join(S)
 
    # Return the modified string
    return S
 
# Driver Code
if __name__ == '__main__':
    S = "ab??"
    K = 2
    print(modifyString(S, K))
     
    # This code is contributed by ipg2016107.


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
public class GFG {
 
  // Function to modify the given String
  // such that String S is a period of K
  static String modifyString(char[] S, int K) {
 
    int N = S.Length;
 
    // Iterate over the range [0, K]
    for (int i = 0; i < K; i++) {
 
      // Stores the frequency of the
      // characters S[i + j*K]
      Dictionary<char, int> M = new Dictionary<char, int>();
 
      // Iterate over the String with
      // increment of K
      for (int j = i; j < N; j += K) {
 
        if (M.ContainsKey(S[j])) {
          M.Add(S[j], M[S[j]] + 1);
        } else {
          M.Add(S[j], 1);
        }
      }
 
      // Print "-1"
      if (M.Count > 2) {
        return "-1";
      } else if (M.Count == 1) {
        if (M['?'] != 0) {
 
          // Replace all characters
          // of the String with '?'
          // to 'a' to make it smallest
          for (int j = i; j < N; j += K) {
            S[j] = 'a';
          }
        }
      }
 
      // Otherwise
      else if (M.Count == 2) {
        char ch = ' ';
 
        // Find the character other
        // than '?'
        foreach (KeyValuePair<char, int> entry in M) {
          if (entry.Key != '?') {
            ch = entry.Key;
          }
        }
 
        // Replace all characters
        // of the String with '?'
        // to character ch
        for (int j = i; j < N; j += K) {
          S[j] = ch;
        }
      }
 
      // Clear the map M
      M.Clear();
    }
 
    // Return the modified String
    return String.Join("",S);
  }
 
  // Driver Code
  public static void Main(String[] args) {
 
    String S = "ab??";
    int K = 2;
    Console.Write(modifyString(S.ToCharArray(), K));
  }
}
 
// This code is contributed by umadevi9616


Javascript




<script>
 
// JavaScript program for the above approach
 
// Function to modify the given string
// such that string S is a period of K
function modifyString(S, K)
{
    let N = S.length;
 
    // Iterate over the range [0, K]
    for(let i = 0; i < K; i++)
    {
         
        // Stores the frequency of the
        // characters S[i + j*K]
        let M = new Map();
 
        // Iterate over the string with
        // increment of K
        for(let j = i; j < N; j += K)
        {
            if (M.has(S[j]))
            {
                M.set(M.get(S[j]),
                      M.get(S[j]) + 1);
            }
            else
            {
                M.set(S[j], 1);
            }
        }
 
        // Print "-1"
        if (M.size > 2)
        {
            return "-1";
        }
        else if (M.size == 1)
        {
            if (M.has('?'))
            {
                 
                // Replace all characters
                // of the string with '?'
                // to 'a' to make it smallest
                for(let j = i; j < N; j += K)
                {
                    S = S.replace(S[j], 'a');
                }
            }
        }
 
        // Otherwise
        else if (M.size == 2)
        {
            let ch;
 
            // Find the character other
            // than '?'
            for(let it of M.keys())
            {
                if (it != '?')
                {
                    ch = it;
                }
            }
 
            // Replace all characters
            // of the string with '?'
            // to character ch
            for(let j = i; j < N; j += K)
            {
                S = S.replace(S[j], ch);
            }
        }
         
        // Clear the map M
        M.clear();
    }
 
    // Return the modified string
    return S;
}
 
// Driver Code
let S = "ab??";
let K = 2;
 
document.write(modifyString(S, K));
 
// This code is contributed by Potta Lokesh
 
</script>


Output: 

abab

 

Time Complexity: O(N)
Auxiliary Space: O(N)