Longest Substring of given Characters by Replacing at Most K Characters for Q Queries


In this problem, we have given M queries, and after performing each query on the given string, we need to print the maximum length of the string having only the ‘ch’ character.

We will use the tabulation method of dynamic programming to find the maximum possible length of the substring after replacing the at most K characters with the given character.

Problem statement − We have given a string alpha of length N and que[] array containing M queries of type {K, ch}, where K is a positive integer, and ch is a character. It is given that for each query, we can replace a maximum of K characters with the character ‘ch’. The given task is to print the maximum length of the substring with only ‘ch’ characters.

Sample examples

Input

alpha = "tutorials"; que = {{1, 't'}, {2, 't'}, {3, 'o'}};

Output

3 4 4 

Explanation 

  • After performing the first query, the string becomes ‘tttorials’. So, the string contains the substring having 3 ‘t’ characters.

  • After performing the second query, the string becomes ‘ttttrials’. So, we can take ‘tttt’ substring.

  • In the third query, the string becomes ‘oooorials’. So, we can take ‘oooo’ substring.

Input

alpha = "nayan"; que = {{1, 'n'}, {2, 'n'}, {3, 'n'}};

Output

2 3 5

Explanation

  • If we replace one character with ‘n’, we get the ‘nn’ as a substring.

  • If we replace two characters with ‘n’, we get the ‘nnn’ substring.

  • After performing the third query, the string becomes ‘nnnnn’, and we can take the whole string as a substring.

Approach 1

In this approach, we will traverse each query and perform each query on the given string. We will define the function to process the query using the dynamic programming approach. In the dynamic programming technique, we can find the maximum length of the substring by including or excluding the particular character in the substring.

Algorithm

Step 1 − Execute the processQueries() function to process queries.

Step 1.1 − In the processQueries() function, initialize the ‘matrix’ array with 0.

Step 1.2 − Next, initialize the matrix[p][0][alpha[p − 1] − 'a'] with 1, as we can take a particular character as a substring. Here, p represents the substring length, q represents the character index, and ‘r’ represents the character index.

Step 1.3 − Start traversing the matrix from 1 to len index. Also, use a nested loop to traverse from 0 to p and another nested loop to traverse all alphabetical characters.

Step 1.4 − If the character at index p – 1 is the same as character r, update the matrix[p][q][r] with the matrix[p − 1][q][r] + 1. We include the current character in this step.

Step 1.5 − Otherwise, update the matrix[p][q][r] with the matrix[p − 1][q − 1][r] + 1. We exclude the current character in this step.

Step 1.6 − Now, fill the process[] array with 0.

Step 1.7 − Travese the matrix, and fill process[p][q] with the max(process[p][q], matrix[r][p][q]). Here, for each index, we store the maximum value.

Step 2 − Define the ‘answer’ list to store the answer of all queries.

Step 3 − Traverse through all queries and get the output for each query.

Step 4 − Take the output value from the process[] array based on the positive integer of query and character and push the result in the ‘answer’ list.

Step 5 − Return the ‘answer’ list.

Example

#include <bits/stdc++.h>
using namespace std;

int matrix[1001][1001][26];
int process[1001][26];
void processQueries(string alpha) {
    int len = alpha.length();
    // Fill array with 0
    memset(matrix, 0, sizeof(matrix));
    for (int p = 1; p <= len; p++) {
        // Length of substring is 1 for characters of substring
        matrix[p][0][alpha[p - 1] - 'a'] = 1;
    }
    for (int p = 1; p <= len; p++) {
        for (int q = 0; q <= p; q++) {
            for (int r = 0; r < 26; r++) {
                // When character at index p is equal to r + 'a', add 1 to the result of previous index
                if (alpha[p - 1] == char(r + 'a')) {
                    matrix[p][q][r] = matrix[p - 1][q][r] + 1;
                } else if (q != 0) {
                    // Q == 0 is already calculated. So, we update only when q != 0
                    matrix[p][q][r] = matrix[p - 1][q - 1][r] + 1;
                }
            }
        }
    }
    // Fill the process[] array with 0.
    memset(process, 0, sizeof(process));
    for (int p = 1; p <= len; p++) {
        for (int q = 0; q < 26; q++) {
            for (int r = 1; r <= len; r++) // Get maximum length
                process[p][q] = max(process[p][q], matrix[r][p][q]);
        }
    }
}
vector<int> performOperations(string alpha, vector<pair<int, char>> &que) {
    processQueries(alpha);
    vector<int> answer;
    // Find answers from process[] array
    for (auto pair : que) {
        answer.push_back(process[pair.first][pair.second - 'a']);
    }
    return answer;
}
int main() {
    string alpha = "tutorials";
    vector<pair<int, char>> que = {{1, 't'}, {2, 't'}, {3, 'o'}};
    vector<int> answer = performOperations(alpha, que);
    cout << "The length of longest substrings after performing the queries are : \n";
    for (int num : answer)
        cout << num << " ";
    return 0;
}

Output

The length of longest substrings after performing the queries are : 
3 4 4

Time complexity − O(N*N + M), where O(N*N) is for processing queries, and O(M) is for traversing queries.

Space complexity − O(M) to store answers for all queries.

In the solution, we have processed the queries first, and after that, we find the answer for each query, which improves the time complexity of the code. Otherwise, we need to process all queries separately.

Updated on: 17-Jul-2023

77 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements