Open In App

Minimum count of distinct Strings by Rotating and Changing characters

Given a string of length N and an integer K. The task is to find the minimum count of distinct strings by changing at most K characters of the string (into any other lowercase letters) and by rotating the string left any number of times.

Examples:



Input : N = 4, S = “abac”, K = 1
Output: 2
Explanation: In the initial string, the number of distinct strings after left rotations is 4, i.e abac -> baca ->acab ->caba. On changing ‘c’ to ‘b’, the string becomes “abab”. For the updated string, the number of distinct strings after left rotations is 2, i.e. abab -> baba. It can be checked that this is the minimum possible number of distinct strings after left rotations by performing the given operation K(=1) times.

Input : N = 10, S = “cccccccccc”, K = 0
Output : 0



Approach: This can be solved with the following idea:

For string S, consider the smallest integer D, which is the divisor of S such that S[i] = S[i + D] =….= S[N – D + i] for all i = 1 to D. Since, this observation is always true for D = N, so such a D always exist. In such a case, the number of distinct strings achievable by left rotation would be D. 

Follow the steps to solve the problem:

Below is the code based on the above approach:




// C++ code for the above approach
#include <bits/stdc++.h>
using namespace std;
#define int long long
 
// Function Change any K characters of
// string S such that number of distinct
// strings after left rotations is minimized
int minimizeNumberOfStrings(int N, int K, string S)
{
 
    // Initialize "ans" by N for
    // worst case
    int ans = N;
 
    // Iterate through l=1 to N. If l is
    // divisor of N, proceed into the loop
    for (int l = 1; l <= N; l++)
        if (N % l == 0) {
 
            // Variable "now" stores the
            // value of the number of
            // characters to be change in
            // the string such the required
            // answer becomes equal to l
            int now = 0;
 
            // Calculation of "now"
            for (int i = 0; i < l; i++) {
                // cnt[] array stores the
                // number of times each
                // character occurs in S
                // at the difference of
                // indices = l
                int cnt[26] = {};
 
                // "mx" stores the value of
                // maximum element of cnt[]
                int mx = 0;
                for (int j = i; j < N; j += l)
                    mx = max(mx, ++cnt[S[j] - 'a']);
 
                // "curr" basically represents
                // the number of characters
                // in S from index i to N,
                // that we are assuming to
                // become same
 
                int curr = N / l;
 
                // "now" is the difference
                // of curr and mx
                now += curr - mx;
            }
 
            // If value of "now" is less
            // than or equal to K, make
            // the "ans" equal to l and
            // break the loop
            if (now <= K) {
                ans = l;
                break;
            }
        }
 
    // Return the final "ans"
    return ans;
}
 
// Driver code
int32_t main()
{
    int N = 4, K = 1;
    string S = "abac";
 
    // Function call
    int answer = minimizeNumberOfStrings(N, K, S);
    cout << answer;
    return 0;
}




// Java code for the above approach
import java.util.*;
 
class GFG
{
   
  // Function Change any K characters of
  // string S such that number of distinct
  // strings after left rotations is minimized
  public static long minimizeNumberOfStrings(int N, int K,
                                             String S)
  {
 
    // Initialize "ans" by N for
    // worst case
    long ans = N;
 
    // Iterate through l=1 to N. If l is
    // divisor of N, proceed into the loop
    for (int l = 1; l <= N; l++) {
      if (N % l == 0) {
 
        // Variable "now" stores the
        // value of the number of
        // characters to be change in
        // the string such the required
        // answer becomes equal to l
        long now = 0;
 
        // Calculation of "now"
        for (int i = 0; i < l; i++) {
          // cnt[] array stores the
          // number of times each
          // character occurs in S
          // at the difference of
          // indices = l
          int[] cnt = new int[26];
 
          // "mx" stores the value of
          // maximum element of cnt[]
          int mx = 0;
          for (int j = i; j < N; j += l) {
            mx = Math.max(
              mx, ++cnt[S.charAt(j) - 'a']);
          }
 
          // "curr" basically represents
          // the number of characters
          // in S from index i to N,
          // that we are assuming to
          // become same
 
          int curr = N / l;
 
          // "now" is the difference
          // of curr and mx
          now += curr - mx;
        }
 
        // If value of "now" is less
        // than or equal to K, make
        // the "ans" equal to l and
        // break the loop
        if (now <= K) {
          ans = l;
          break;
        }
      }
    }
 
    // Return the final "ans"
    return ans;
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int N = 4, K = 1;
    String S = "abac";
 
    // Function call
    long answer = minimizeNumberOfStrings(N, K, S);
    System.out.println(answer);
  }
}




# Function to change any K characters of string S
# such that the number of distinct strings after
# left rotations is minimized
 
 
def minimizeNumberOfStrings(N, K, S):
    # Initialize "ans" by N for worst case
    ans = N
 
    # Iterate through l=1 to N//2 (excluding N)
    # If l is a divisor of N, proceed into the loop
    for l in range(1, N//2+1):
        if N % l == 0:
            # Variable "now" stores the value of the number
            # of characters to be change in the string such
            # the required answer becomes equal to l
            now = 0
 
            # Calculation of "now"
            for i in range(l):
                # cnt[] array stores the number of times
                # each character occurs in S at the
                # difference of indices = l
                cnt = [0] * 26
                mx = 0
 
                for j in range(i, N, l):
                    cnt[ord(S[j])-ord('a')] += 1
                    mx = max(mx, cnt[ord(S[j])-ord('a')])
 
                # curr basically represents the number of
                # characters in S from index i to N, that we
                # are assuming to become the same
                curr = N // l
 
                # "now" is the difference of curr and mx
                now += curr - mx
 
            # If value of "now" is less than or equal to K,
            # make the "ans" equal to l and break the loop
            if now <= K:
                ans = l
                break
 
    # Return the final "ans"
    return ans
 
 
# Driver code
if __name__ == '__main__':
    N = 4
    K = 1
    S = "abac"
 
    # Function call
    answer = minimizeNumberOfStrings(N, K, S)
    print(answer)




using System;
 
class GFG {
    // Function Change any K characters of
    // string S such that number of distinct
    // strings after left rotations is minimized
    static long MinimizeNumberOfStrings(int N, int K,
                                        string S)
    {
        // Initialize "ans" by N for worst case
        int ans = N;
 
        // Iterate through l=1 to N. If l is
        // divisor of N, proceed into the loop
        for (int l = 1; l <= N; l++) {
            if (N % l == 0) {
                // Variable "now" stores the
                // value of the number of
                // characters to be changed in
                // the string such that the required
                // answer becomes equal to l
                int now = 0;
 
                // Calculation of "now"
                for (int i = 0; i < l; i++) {
                    // cnt[] array stores the
                    // number of times each
                    // character occurs in S
                    // at the difference of
                    // indices = l
                    int[] cnt = new int[26];
 
                    // "mx" stores the value of
                    // maximum element of cnt[]
                    int mx = 0;
                    for (int j = i; j < N; j += l) {
                        mx = Math.Max(mx,
                                      ++cnt[S[j] - 'a']);
                    }
 
                    // "curr" basically represents
                    // the number of characters
                    // in S from index i to N,
                    // that we are assuming to
                    // become same
                    int curr = N / l;
 
                    // "now" is the difference
                    // of curr and mx
                    now += curr - mx;
                }
 
                // If value of "now" is less
                // than or equal to K, make
                // the "ans" equal to l and
                // break the loop
                if (now <= K) {
                    ans = l;
                    break;
                }
            }
        }
 
        // Return the final "ans"
        return ans;
    }
 
    // Driver code
    static void Main(string[] args)
    {
        int N = 4, K = 1;
        string S = "abac";
 
        // Function call
        int answer = (int)MinimizeNumberOfStrings(N, K, S);
        Console.WriteLine(answer);
    }
}




function minimizeNumberOfStrings(N, K, S) {
  let ans = N; // Initialize "ans" by N for worst case
 
  for (let l = 1; l <= N; l++) {
    if (N % l == 0) { // If l is a divisor of N, proceed into the loop
      let now = 0; // Variable "now" stores the value of the number of characters to be changed in the string such that the required answer becomes equal to l
      for (let i = 0; i < l; i++) {
        let cnt = new Array(26).fill(0); // cnt[] array stores the number of times each character occurs in S at the difference of indices = l
        let mx = 0; // "mx" stores the value of maximum element of cnt[]
        for (let j = i; j < N; j += l) {
          mx = Math.max(mx, ++cnt[S.charCodeAt(j) - 'a'.charCodeAt()]); // Calculate the maximum count of any character in the substring of length l starting from i and jumping l indices
        }
        let curr = Math.floor(N / l); // "curr" basically represents the number of characters in S from index i to N that we are assuming to become same
        now += curr - mx; // "now" is the difference of curr and mx, representing the number of characters to be changed to make them all same
      }
      if (now <= K) { // If value of "now" is less than or equal to K, make the "ans" equal to l and break the loop
        ans = l;
        break;
      }
    }
  }
  return ans; // Return the final "ans"
}
 
// example usage:
let N = 4, K = 1;
let S = "abac";
let answer = minimizeNumberOfStrings(N, K, S);
console.log(answer);

Output
2

Time Complexity: O(N2)
Auxiliary Space: O(1)


Article Tags :