Minimizing Operations to Rewrite a String
Last Updated :
28 Nov, 2023
Given a string S, you have to write the same given string using two operations, the task is to find the minimum number of operations to write it.
- You can only write a sequence of the same character each time.
- You can choose any substring and overwrite the existing characters with single new characters.
Examples:
Input: s = "aaaddd"
Output: 2
Explanation: Write "aaa" first and then write "ddd".
Input: s = "aca"
Output: 2
Explanation: Write "aaa" first and then write "c" from the second place of the string, which will cover the existing character 'a'.
Minimizing Operations to Rewrite a String using Dynamic Programming.
This problem is easier to solve if we reduce it to subproblems using Divide and Conquer. We can break it down into smaller subproblems, we keep dividing s until the substring contains 1 or 2 characters (as the base case). We'll define a DP table dp, where dp[i][j] will represent the minimum number of operations needed to write the substring s[i...j] (inclusive).
Base Case:For a single character (substring of length 1), we need only one operation to write it. Therefore, dp[i][i] = 1 for all i.
Recursive Formula: Now, we need to find the minimum number of operations for substrings of length 2, 3, and so on, up to the entire string length.
- For each substring length, we'll iterate over all possible starting points (i) and ending points (j) of that substring.
- To compute dp[i][j], we'll iterate over all possible k from i to j-1 (inclusive).
- For each k, we'll try to find the minimum number of operations by combining the minimum operations required to write s[i...k] and s[k+1...j].
Final Answer: The answer to the problem will be stored in dp[0][n-1], where n is the length of the string.
Below is the implementation of the above approach:
C++
// C++ code for the above approach:
#include <climits>
#include <iostream>
#include <vector>
using namespace std;
int writeString(string s)
{
int n = s.length();
vector<vector<int> > dp(n, vector<int>(n, 0));
for (int i = n - 1; i >= 0; --i) {
// Base case: writing one character
// always takes 1 operation.
// Example: 'a' -> 1 operation
dp[i][i] = 1;
for (int j = i + 1; j < n; ++j) {
dp[i][j] = INT_MAX;
// Iterate through partition points k
for (int k = i; k < j; ++k) {
// Calculate the minimum operations
// for writing s[i...k] and s[k+1...j]
int minOperations = dp[i][k] + dp[k + 1][j];
// If s[i] and s[j] are the same,
// we need one less turn because
// we can write both characters
// in a single operation only.
if (s[i] == s[j])
minOperations--; // Example: 'aabaa' ->
// Operations req: 2
// instead of 3
// Update dp[i][j] with the minimum
// operations for s[i...j]
dp[i][j] = min(dp[i][j], minOperations);
}
}
}
// Minimum operation for writing the entire
// string s[0...n-1]
return dp[0][n - 1];
}
// Drivers code
int main()
{
string s = "aabca";
// Function Call
cout << writeString(s);
return 0;
}
Java
public class WriteString {
public static int writeString(String s)
{
int n = s.length();
int[][] dp = new int[n][n];
for (int i = n - 1; i >= 0; i--) {
// Base case: writing one character
// always takes 1 operation.
// Example: 'a' -> 1 operation
dp[i][i] = 1;
for (int j = i + 1; j < n; j++) {
dp[i][j] = Integer.MAX_VALUE;
// Iterate through partition points k
for (int k = i; k < j; k++) {
// Calculate the minimum operations
// for writing s[i...k] and s[k+1...j]
int minOperations
= dp[i][k] + dp[k + 1][j];
// If s[i] and s[j] are the same,
// we need one less turn because
// we can write both characters
// in a single operation only.
if (s.charAt(i) == s.charAt(j))
minOperations--; // Example: 'aabaa'
// -> Operations
// req: 2 instead
// of 3
// Update dp[i][j] with the minimum
// operations for s[i...j]
dp[i][j]
= Math.min(dp[i][j], minOperations);
}
}
}
// Minimum operation for writing the entire
// string s[0...n-1]
return dp[0][n - 1];
}
public static void main(String[] args)
{
String s = "aabca";
// Function Call
System.out.println(writeString(s));
}
}
Python3
def writeString(s):
n = len(s)
dp = [[0] * n for _ in range(n)]
for i in range(n - 1, -1, -1):
# Base case: writing one character
# always takes 1 operation.
# Example: 'a' -> 1 operation
dp[i][i] = 1
for j in range(i + 1, n):
dp[i][j] = float('inf')
# Iterate through partition points k
for k in range(i, j):
# Calculate the minimum operations
# for writing s[i...k] and s[k+1...j]
minOperations = dp[i][k] + dp[k + 1][j]
# If s[i] and s[j] are the same,
# we need one less turn because
# we can write both characters
# in a single operation only.
if s[i] == s[j]:
minOperations -= 1 # Example: 'aabaa' ->
# Operations req: 2
# instead of 3
# Update dp[i][j] with the minimum
# operations for s[i...j]
dp[i][j] = min(dp[i][j], minOperations)
# Minimum operation for writing the entire
# string s[0...n-1]
return dp[0][n - 1]
# Drivers code
s = "aabca"
# Function Call
print(writeString(s))
C#
using System;
class MainClass
{
static int WriteString(string s)
{
int n = s.Length;
int[,] dp = new int[n, n];
for (int i = n - 1; i >= 0; i--)
{
// Base case: writing one character
// always takes 1 operation.
dp[i, i] = 1;
for (int j = i + 1; j < n; j++)
{
dp[i, j] = int.MaxValue;
// Iterate through partition points k
for (int k = i; k < j; k++)
{
// Calculate the minimum operations
// for writing s[i...k] and s[k+1...j]
int minOperations = dp[i, k] + dp[k + 1, j];
// If s[i] and s[j] are the same,
// we need one less turn because
// we can write both characters
// in a single operation only.
if (s[i] == s[j])
minOperations--; // Example: 'aabaa' ->
// Operations req: 2
// instead of 3
// Update dp[i, j] with the minimum
// operations for s[i...j]
dp[i, j] = Math.Min(dp[i, j], minOperations);
}
}
}
// Minimum operation for writing the entire
// string s[0...n-1]
return dp[0, n - 1];
}
// Drivers code
public static void Main(string[] args)
{
string s = "aabca";
// Function Call
Console.WriteLine(WriteString(s));
}
}
JavaScript
function writeString(s) {
const n = s.length;
// Initialize dp array with dimensions n x n
const dp = new Array(n).fill(0).map(() => new Array(n).fill(0));
// Bottom-up approach to fill the dp array
for (let i = n - 1; i >= 0; --i) {
// Base case: writing one character always takes 1 operation.
dp[i][i] = 1; // Example: 'a' -> 1 operation
for (let j = i + 1; j < n; ++j) {
dp[i][j] = Infinity;
// Iterate through partition points k
for (let k = i; k < j; ++k) {
// Calculate the minimum operations for writing s[i...k] and s[k+1...j]
let minOperations = dp[i][k] + dp[k + 1][j];
// If s[i] and s[j] are the same, we need one less turn because we can write both characters in a single operation only.
if (s[i] === s[j]) {
minOperations--; // Example: 'aabaa' -> Operations req: 2 instead of 3
}
// Update dp[i][j] with the minimum operations for s[i...j]
dp[i][j] = Math.min(dp[i][j], minOperations);
}
}
}
// Minimum operation for writing the entire string s[0...n-1]
return dp[0][n - 1];
}
// Test string
const s = "aabca";
// Function Call
console.log(writeString(s));
Time Complexity: O(n^3), where n is length of given string.
Auxiliary Space: O(n*n)
Similar Reads
Minimize operations to restore original string by permutation Given a string S and permutation P, both of length N. In one operation you can change the position of each and every character of the string from S[i] to S[P[i]]. Determine the minimum number of operations to restore the original string. Examples: Input: S = "ababa", P = [3, 4, 5, 2, 1] Output: 1Exp
8 min read
Minimum operations to convert String A to String B Given two strings consisting of lowercase alphabets A and B, both of the same length. Each character of both the strings is either a lowercase letter or a question mark '?'. The task is to find the minimum number of operations required to convert A to B, in one operation you can choose an index i, i
12 min read
Final string after performing given operations Given a string str containing only characters x and y, the task is to perform the following operations while possible: Find an index such that s[i] = 'x' and s[i+1] = 'y' and delete both the characters s[i] and s[i+1], if no such index is found then find an index such that s[i] = 'y' and s[i+1] = 'x
6 min read
Find the minimum operations required to type the given String Geek is extremely punctual but today even he is not feeling like doing his homework assignment. He must start doing it immediately in order to meet the deadline. For the assignment, Geek needs to type a string s.To reduce his workload, he has decided to perform one of the following two operations ti
4 min read
Modify a string by performing given shift operations Given a string S containing lowercase English alphabets, and a matrix shift[][] consisting of pairs of the form{direction, amount}, where the direction can be 0 (for left shift) or 1 (for right shift) and the amount is the number of indices by which the string S is required to be shifted. The task i
6 min read