Minimum number of swaps required to make the string K periodic

• Difficulty Level : Medium
• Last Updated : 24 May, 2021

Given a string S of length N, and an array A, consisting of lowercase letters. Also given a positive integer K. the task is to find the minimum number of swaps required (between S and A) to make string S K periodic.
Note:

• A string is said to be K periodic, if for each position i in the string S[i] = S[i+K].
• In one move, only one character of S can be swapped with a character of A.
• The characters in A can be used more than once.

Examples:

Input: S = “nihsiakyt”, K = 3, A = [‘n’, ‘i’, ‘p’, ‘s’, ‘q’]
Output:
Explanation:
Considering 0 based positioning for the string S:
Positions 3, 6 should be replaced with ‘n’.
Position 7 should be replaced with ‘i’.
Positions 2, 5, 8 can be replaced with any character from A to make the string K periodic.
Final 3 periodic string: “nisnisnis”
Therefore minimum swaps required = 6
Input: S = “abcdeactr”, K = 4, A = [‘a’, ‘c’, ‘p’]
Output:
Explanation:
In total 5 changes are needed to make the string 4 periodic.

Approach: This problem can be solved with help of frequency counting and hashing.

1. To solve the problem mentioned above we use a 2-dimensional array freq[K] to store frequency of characters at position j % K for all .
2. Use a boolean array to mark all characters present in array A.
3. For all characters in range 0 to K there will be N / K or (N / K + 1) characters which should be same.
4. So for all such characters we check which character has the maximum frequency at position i and is also present in array A.
5. Add that to the answer, i.e. .
6. We will also add 1 to the answer if 7. because there will be N / K + 1 characters for all such characters i.

Below is the implementation of above approach:

C++

 // C++ code to find the minimum// number of swaps required to// make the string K periodic #include using namespace std; int minFlip(string s, int n,            int k, char a[],            int p){    bool allowed = { 0 };     for (int i = 0; i < p; i++) {         // Mark all allowed        // characters as true        allowed[a[i] - 'a'] = true;    }    char freq[k];     // Initialize the freq array to 0    for (int i = 0; i < k; i++)        for (int j = 0; j < 26; j++)            freq[i][j] = 0;     for (int i = 0; i < n; i++) {         // Increase the frequency        // of each character        freq[i % k][s[i] - 'a'] += 1;    }     int ans = 0;     // Total number of periods of    // size K in the string    int totalpositions = n / k;     for (int i = 0; i < k; i++) {        int maxfrequency = 0;         for (int j = 0; j < 26; j++) {             // Check if the current character            // is present in allowed            // and whether the current            // frequency is greater than            // all previous frequencies            // for this position            if (freq[i][j] > maxfrequency                and allowed[j] == true)                maxfrequency = freq[i][j];        }         // update the answer by        // subtracting the maxfrequency        // from total positions        // if there exist extra character        // at the end of the string        // apart from the n/k characters        // then add 1.        ans            += (totalpositions                - maxfrequency                + ((i % k < n % k)                       ? 1                       : 0));    }    cout << ans << endl;} // Driver codeint main(){    string S = "nihsiakyt";    int n = S.length();     int K = 3;     char A        = { 'n', 'i', 'p', 's', 'q' };    int p = sizeof(A) / sizeof(A);     minFlip(S, n, K, A, p);     return 0;}

Java

 // Java code to find the minimum// number of swaps required to// make the String K periodicimport java.util.*; class GFG{ static void minFlip(String s, int n,                    int k, char a[],                    int p){    boolean allowed[] = new boolean;     for(int i = 0; i < p; i++)    {               // Mark all allowed       // characters as true       allowed[a[i] - 'a'] = true;    }    char [][]freq = new char[k];     // Initialize the freq array to 0    for(int i = 0; i < k; i++)       for(int j = 0; j < 26; j++)          freq[i][j] = 0;     for(int i = 0; i < n; i++)    {               // Increase the frequency       // of each character       freq[i % k][s.charAt(i) - 'a'] += 1;    }     int ans = 0;     // Total number of periods    // of size K in the String    int totalpositions = n / k;     for(int i = 0; i < k; i++)    {       int maxfrequency = 0;       for(int j = 0; j < 26; j++)       {                     // Check if the current character          // is present in allowed          // and whether the current          // frequency is greater than          // all previous frequencies          // for this position          if (freq[i][j] > maxfrequency &&              allowed[j] == true)              maxfrequency = freq[i][j];       }               // Update the answer by       // subtracting the maxfrequency       // from total positions       // if there exist extra character       // at the end of the String       // apart from the n/k characters       // then add 1.       ans += (totalpositions -                 maxfrequency +                  ((i % k < n %                    k) ? 1 : 0));    }    System.out.print(ans + "\n");} // Driver codepublic static void main(String[] args){    String S = "nihsiakyt";    int n = S.length();    int K = 3;     char []A = { 'n', 'i', 'p', 's', 'q' };    int p = A.length;     minFlip(S, n, K, A, p);}} // This code is contributed by Amit Katiyar

Python3

 # Python3 code to find the minimum# number of swaps required to# make the string K periodicdef minFlip(s, n, k, a, p):     allowed =  * 26     for i in range(p):         # Mark all allowed        # characters as true        allowed[ord(a[i]) - ord('a')] = True             freq = [[0 for x in range(26)]               for y in range(k)]     # Initialize the freq array to 0    for i in range(k):        for j in range(26):            freq[i][j] = 0     for i in range(n):         # Increase the frequency        # of each character        freq[i % k][ord(s[i]) - ord('a')] += 1     ans = 0     # Total number of periods of    # size K in the string    totalpositions = n // k     for i in range(k):        maxfrequency = 0        for j in range(26):             # Check if the current character            # is present in allowed            # and whether the current            # frequency is greater than            # all previous frequencies            # for this position            if (freq[i][j] > maxfrequency and                allowed[j] == True):                maxfrequency = freq[i][j]         # Update the answer by        # subtracting the maxfrequency        # from total positions        # if there exist extra character        # at the end of the string        # apart from the n/k characters        # then add 1.        ans += (totalpositions - maxfrequency)        if (i % k < n % k):            ans += 1             print(ans) # Driver codeif __name__ == "__main__":     S = "nihsiakyt"    n = len(S)     K = 3     A = [ 'n', 'i', 'p', 's', 'q' ]    p = len(A)     minFlip(S, n, K, A, p) # This code is contributed by chitranayal

C#

 // C# code to find the minimum// number of swaps required to// make the String K periodicusing System; class GFG{ static void minFlip(String s, int n,                    int k, char []a,                    int p){    bool []allowed = new bool;     for(int i = 0; i < p; i++)    {               // Mark all allowed       // characters as true       allowed[a[i] - 'a'] = true;    }    char [,]freq = new char[k, 26];     // Initialize the freq array to 0    for(int i = 0; i < k; i++)       for(int j = 0; j < 26; j++)          freq[i, j] = (char)0;     for(int i = 0; i < n; i++)    {               // Increase the frequency       // of each character       freq[i % k, s[i] - 'a'] += (char)1;    }     int ans = 0;     // Total number of periods    // of size K in the String    int totalpositions = n / k;     for(int i = 0; i < k; i++)    {       int maxfrequency = 0;       for(int j = 0; j < 26; j++)       {           // Check if the current character          // is present in allowed          // and whether the current          // frequency is greater than          // all previous frequencies          // for this position          if (freq[i, j] > maxfrequency &&              allowed[j] == true)              maxfrequency = freq[i, j];       }               // Update the answer by       // subtracting the maxfrequency       // from total positions       // if there exist extra character       // at the end of the String       // apart from the n/k characters       // then add 1.       ans += (totalpositions -                 maxfrequency +                  ((i % k < n %                    k) ? 1 : 0));    }    Console.Write(ans + "\n");} // Driver codepublic static void Main(String[] args){    String S = "nihsiakyt";    int n = S.Length;    int K = 3;     char []A = { 'n', 'i', 'p', 's', 'q' };    int p = A.Length;     minFlip(S, n, K, A, p);}} // This code is contributed by Rohit_ranjan

Javascript


Output:
6

My Personal Notes arrow_drop_up