Open In App

Minimum count of distinct Strings by Rotating and Changing characters

Last Updated : 02 Aug, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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:

  • Iterate through all the divisors of N.
  • For the current divisor (say ‘l’), calculate the minimum number of characters in the string that need to be changed (say “now”) such that the string satisfies the condition mentioned in the observation.
  • This can be easily calculated with the help of an array (say cnt[]) that stores the number of occurrences of each character in the string at a distance of ‘l’.
  • If the calculated value of “now” is smaller than K, then return that, else proceed for the next iteration (i.e. check the same for the next divisor of N).

Below is the code based on the above approach:

C++




// 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




// 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);
  }
}


Python3




# 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)


C#




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);
    }
}


Javascript




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)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads