Open In App

Minimum characters to be replaced in Ternary string to remove all palindromic substrings for Q queries

Given a ternary string S of length N containing only ‘0’, ‘1’ and ‘2’ characters and Q queries containing a range of indices [L, R], the task for each query [L, R] is to find the minimum number of characters to convert to either ‘0’, ‘1’ or ‘2’ such that there exists no palindromic substring of length at least 2, between str[L] and str[R].

Examples:



Input: N = 10, Q = 3, S = “0200011011”, queries = {0, 4}, {1, 6}, {2, 8}
Output: 2 3 3
Explanation:  
Query 1: {0, 4} ? s = “02000” palindromic substrings present are “020”, “00”, “000”. Substring s can be changed to “02102” with 2 changes. “acbac” has zero palindromic substrings.
Query 2: {1, 6} ? s = “200011” palindromic substrings present are “00”, “000”, “11”. Substring s can be changed to “201201″ with 3 changes. “cabcab” has zero palindromic substrings. 
Query 3: {2,  8} ? s = “aaabbab” palindromic substrings  present are”00″, “000”, “0110”, “11”, “101”. Substring s can be changed to “1201201″ with 3 changes. “1201201” has zero palindromic substrings.

Input: N = 5, Q = 2, S = “bccab”, queries = {0, 4}, {1, 2}
Output: 2 1



Naive Approach: The given problem can be solved by recursively modifying each character of the substring for a given query and checking if the resultant substring has palindromic substrings.

Time Complexity: O(Q*3N)
Auxiliary Space: O(N)

Efficient Approach: The given problem can be solved using Dynamic Programming, the idea is to preprocess the possible answers for all substrings using the following observations:

Now, each query can be solved by transforming the substring from L to R character into the six target strings and checking which of them requires the least operations. This approach requires O(N) time for each query. The approach can be optimized further by preprocessing the given string. Following is the optimized solution:

Below is the implementation of the above approach:




// C++ program for the above approach
 
#include <bits/stdc++.h>
#define SIZE 100005
using namespace std;
 
// Function to preprocess the cost of
// converting the first j character to
// each sequence prefix[i]
void preprocess(string& s, string& t,
                int prefix[][SIZE],
                int n, int i)
{
    // Initialize DP array
    prefix[i][0] = (s[0] != t[0]);
 
    for (int j = 1; j < n; j++) {
 
        // prefix[i][j] defines minimum
        // operations to transform first j
        // characters of s into sequence i
        prefix[i][j]
            = prefix[i][j - 1]
              + (s[j] != t[j % 3]);
    }
    return;
}
 
// Function to find the minimum number of
// changes required to make each substring
// between [L, R] non-palindromic
void minChangesNonPalindrome(
    string str, int N, int Q,
    vector<pair<int, int> > queries)
{
 
    // Initialize the DP array
    int prefix[6][SIZE];
 
    // Initialize the 6 different patterns
    // that can be formed to make substrings
    // non palindromic
    vector<string> sequences
        = { "012", "021", "102",
            "120", "201", "210" };
 
    for (int i = 0; i < 6; i++) {
 
        // Preprocess the string with
        // the ith sequence
        preprocess(str, sequences[i],
                   prefix, N, i);
    }
 
    // Iterate through queries
    for (int i = 0; i < Q; i++) {
 
        int l = queries[i].first + 1,
            r = queries[i].second + 1;
        int cost = INT_MAX;
 
        // Find the minimum operations by
        // comparing 6 different patterns
        // of the substrings
        for (int j = 0; j < 6; j++) {
 
            // Find the cost
            cost
                = min(
                    cost,
                    prefix[j][r]
                        - prefix[j][l]
                        + (str[l] != sequences[j][l % 3]));
        }
        cout << cost << '\n';
    }
}
 
// Driver Code
int main()
{
    string S = "0200011011";
    vector<pair<int, int> > queries
        = { { 0, 4 }, { 1, 6 }, { 2, 8 } };
    int N = S.length();
    int Q = queries.size();
 
    minChangesNonPalindrome(
        S, N, Q, queries);
 
    return 0;
}




import java.util.*;
import java.io.*;
 
// Java program for the above approach
class GFG{
 
    public static int SIZE = 100005;
 
    // Function to preprocess the cost of
    // converting the first j character to
    // each sequence prefix[i]
    public static void preprocess(String s, String t, int prefix[][], int n, int i)
    {
        // Initialize DP array
        prefix[i][0] = ((s.charAt(0) != t.charAt(0)) ? 1 : 0);
 
        for (int j = 1; j < n; j++) {
 
            // prefix[i][j] defines minimum
            // operations to transform first j
            // characters of s into sequence i
            prefix[i][j] = prefix[i][j - 1] + (s.charAt(j) != t.charAt(j%3) ? 1 : 0);
        }
    }
 
    // Function to find the minimum number of
    // changes required to make each substring
    // between [L, R] non-palindromic
    public static void minChangesNonPalindrome(String str, int N, int Q, ArrayList<ArrayList<Integer>> queries)
    {
 
        // Initialize the DP array
        int prefix[][] = new int[6][SIZE];
 
        // Initialize the 6 different patterns
        // that can be formed to make substrings
        // non palindromic
        ArrayList<String> sequences = new ArrayList<String>(
            List.of(
                "012",
                "021",
                "102",
                "120",
                "201",
                "210"
            )
        );
 
        for (int i = 0; i < 6; i++) {
 
            // Preprocess the string with
            // the ith sequence
            preprocess(str, sequences.get(i), prefix, N, i);
        }
 
        // Iterate through queries
        for (int i = 0 ; i < Q ; i++) {
 
            int l = queries.get(i).get(0) + 1,
            r = queries.get(i).get(1) + 1;
            int cost = Integer.MAX_VALUE;
 
            // Find the minimum operations by
            // comparing 6 different patterns
            // of the substrings
            for (int j = 0 ; j < 6 ; j++) {
 
                // Find the cost
                cost = Math.min(cost, prefix[j][r] - prefix[j][l] + (str.charAt(l) != sequences.get(j).charAt(l % 3) ? 1 : 0));
            }
            System.out.println(cost);
        }
    }
 
 
    // Driver code
    public static void main(String args[])
    {
        String S = "0200011011";
        ArrayList<ArrayList<Integer>> queries = new ArrayList<ArrayList<Integer>>(
            List.of(
                new ArrayList<Integer>(
                    List.of(0, 4)
                ),
                new ArrayList<Integer>(
                    List.of(1, 6)
                ),
                new ArrayList<Integer>(
                    List.of(2, 8)
                )
            )
        );
        int N = S.length();
        int Q = queries.size();
 
        minChangesNonPalindrome(S, N, Q, queries);
    }
}
 
// This code is contributed by subhamgoyal2014.




# Python 3 program for the above approach
import sys
SIZE = 100005
 
# Function to preprocess the cost of
# converting the first j character to
# each sequence prefix[i]
def preprocess(s,  t,
               prefix,
               n, i):
 
    # Initialize DP array
    prefix[i][0] = (s[0] != t[0])
 
    for j in range(1, n):
 
        # prefix[i][j] defines minimum
        # operations to transform first j
        # characters of s into sequence i
        prefix[i][j] = prefix[i][j - 1] + (s[j] != t[j % 3])
    return
 
# Function to find the minimum number of
# changes required to make each substring
# between [L, R] non-palindromic
def minChangesNonPalindrome(
        st, N, Q,
        queries):
 
    # Initialize the DP array
    prefix = [[0 for x in range(SIZE)]for y in range(6)]
 
    # Initialize the 6 different patterns
    # that can be formed to make substrings
    # non palindromic
    sequences = ["012", "021", "102",
                 "120", "201", "210"]
 
    for i in range(6):
 
        # Preprocess the string with
        # the ith sequence
        preprocess(st, sequences[i],
                   prefix, N, i)
 
    # Iterate through queries
    for i in range(Q):
 
        l = queries[i][0] + 1
        r = queries[i][1] + 1
        cost = sys.maxsize-1
 
        # Find the minimum operations by
        # comparing 6 different patterns
        # of the substrings
        for j in range(6):
 
            # Find the cost
            cost = min(cost, prefix[j][r] - prefix[j][l]
                       + (st[l] != sequences[j][l % 3]))
 
        print(cost)
 
# Driver Code
if __name__ == "__main__":
 
    S = "0200011011"
    queries = [[0, 4], [1, 6], [2, 8]]
    N = len(S)
    Q = len(queries)
 
    minChangesNonPalindrome(
        S, N, Q, queries)
 
    # This code is contributed by ukasp.




// C# program for the above approach
using System;
class GFG {
 
  // Function to preprocess the cost of
  // converting the first j character to
  // each sequence prefix[i]
  static void preprocess(string s, string t,
                         int[, ] prefix, int n, int i)
  {
    // Initialize DP array
    prefix[i, 0] = 0;
    if (s[0] != t[0])
      prefix[i, 0] = 1;
 
    for (int j = 1; j < n; j++) {
 
      // prefix[i][j] defines minimum
      // operations to transform first j
      // characters of s into sequence i
      int count = 0;
      if (s[j] != t[j % 3])
        count++;
      prefix[i, j] = prefix[i, j - 1] + count;
    }
    return;
  }
 
  // Function to find the minimum number of
  // changes required to make each substring
  // between [L, R] non-palindromic
  static void minChangesNonPalindrome(string str, int N,
                                      int Q,
                                      int[, ] queries)
  {
 
    // Initialize the DP array
    int[, ] prefix = new int[6, 100005];
    // Initialize the 6 different patterns
    // that can be formed to make substrings
    // non palindromic
    string[] sequences
      = { "012", "021", "102", "120", "201", "210" };
 
    for (int i = 0; i < 6; i++) {
 
      // Preprocess the string with
      // the ith sequence
      preprocess(str, sequences[i], prefix, N, i);
    }
 
    // Iterate through queries
    for (int i = 0; i < Q; i++) {
 
      int l = queries[i, 0] + 1, r
        = queries[i, 1] + 1;
      int cost = Int32.MaxValue;
 
      // Find the minimum operations by
      // comparing 6 different patterns
      // of the substrings
      for (int j = 0; j < 6; j++) {
 
        // Find the cost
        int count = 0;
        if (str[l] != sequences[j][l % 3])
          count++;
        cost = Math.Min(cost, prefix[j, r]
                        - prefix[j, l]
                        + count);
      }
      Console.WriteLine(cost);
    }
  }
  static void Main()
  {
    string S = "0200011011";
    int[, ] queries = { { 0, 4 }, { 1, 6 }, { 2, 8 } };
    int N = S.Length;
    int Q = 3;
 
    minChangesNonPalindrome(S, N, Q, queries);
  }
}
 
// This code is contributed by garg28harsh.




<script>
 
        // JavaScript Program to implement
        // the above approach
        let SIZE = 100005
 
        // Function to preprocess the cost of
        // converting the first j character to
        // each sequence prefix[i]
        function preprocess(s, t,
            prefix, n, i)
           {
         
            // Initialize DP array
            prefix[i][0] = (s[0] != t[0]);
 
            for (let j = 1; j < n; j++) {
 
                // prefix[i][j] defines minimum
                // operations to transform first j
                // characters of s into sequence i
                prefix[i][j]
                    = prefix[i][j - 1]
                    + (s[j] != t[j % 3]);
            }
            return prefix;
        }
 
        // Function to find the minimum number of
        // changes required to make each substring
        // between [L, R] non-palindromic
        function minChangesNonPalindrome(
            str, N, Q, queries)
        {
 
            // Initialize the DP array
            let prefix = new Array(6);
            for (let i = 0; i < prefix.length; i++)
                prefix[i] = new Array(SIZE).fill(0);
 
            // Initialize the 6 different patterns
            // that can be formed to make substrings
            // non palindromic
            let sequences
                = ["012", "021", "102",
                    "120", "201", "210"];
 
            for (let i = 0; i < 6; i++) {
 
                // Preprocess the string with
                // the ith sequence
                prefix = preprocess(str, sequences[i],
                    prefix, N, i);
            }
 
            // Iterate through queries
            for (let i = 0; i < Q; i++) {
 
                let l = queries[i].first + 1,
                    r = queries[i].second + 1;
                let cost = Number.MAX_VALUE;
 
                // Find the minimum operations by
                // comparing 6 different patterns
                // of the substrings
                for (let j = 0; j < 6; j++) {
 
                    // Find the cost
                    cost
                        = Math.min(
                            cost,
                            prefix[j][r]
                            - prefix[j][l]
                            + (str[l] != sequences[j][l % 3]));
                }
                document.write(cost + '<br>');
            }
        }
 
        // Driver Code
        let S = "0200011011";
        let queries
            = [{ first: 0, second: 4 }, { first: 1, second: 6 }, { first: 2, second: 8 }];
        let N = S.length;
        let Q = queries.length;
 
        minChangesNonPalindrome(
            S, N, Q, queries);
 
    // This code is contributed by Potta Lokesh
    </script>

Output: 
2
3
3

 

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


Article Tags :