Open In App

Minimum operations to transform given string to another by moving characters to front or end

Improve
Improve
Like Article
Like
Save
Share
Report

Given two Strings S and T of length N consisting of lowercase alphabets, which are permutations of each other, the task is to print the minimum number of operations to convert S to T. In one operation, pick any character of the string S and move it either to the start or end of the string S.

Examples:

Input: S = “abcde”, T = “edacb”
Output: 3
Explanation:
We can convert S to T in 3 moves:
1. move ‘d’ to start: “dabce” 
2. move ‘e’ to start: “edabc” 
3. move ‘b’ to end: “edacb”

Input: S = “dcdb”, T = “ddbc”
Output: 1
Explanation:
Move ‘c’ to end

Naive Approach: The naive approach is to try all possibilities of swapping a character. One can put some character to the front, to the end, or can leave it in the same position. The above three operations can be solved using recursion and print the minimum number of steps required after all the steps.
Time Complexity: O(3N), where N is the length of the given string.
Auxiliary Space: O(1)

Efficient Approach: To optimize the above approach, the idea is to observe that after moving the characters of the string S, the unchanged characters come together to form a contiguous substring in T. So, if we can maximize the length of this subsequence, then the count of operations to convert string S to T is:

N – length of the longest contiguous substring of T that is a subsequence of S

Therefore, to find the length of the longest contiguous substring of T that is a subsequence of string S, find the longest common subsequence of S and T. Let dp[][] stores the length of the longest contiguous substring of T that is a subsequence of string S, . Now dp[i][j] will store the length of the longest suffix of T[0, …, j] that is also a subsequence of S[0, …, i]. The recurrence relation is given by: 

  • If i is greater than 0, dp[i][j] = max(dp[i-1][j], dp[i][j]).
  • If S[i] is equals to T[i] then, dp[i][j] = 1 + dp[i-1][j-1].

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
int dp[1010][1010];
 
// Function that finds the minimum number
// of steps to find the minimum characters
// must be moved to convert string s to t
int solve(string s, string t)
{
 
    int n = s.size();
 
    // r = maximum value over all
    // dp[i][j] computed so far
    int r = 0;
 
    // dp[i][j] stores the longest
    // contiguous suffix of T[0..j]
    // that is subsequence of S[0..i]
    for (int i = 0; i < n; i++) {
 
        for (int j = 0; j < n; j++) {
 
            dp[i][j] = 0;
            if (i > 0) {
 
                dp[i][j] = max(dp[i - 1][j],
                               dp[i][j]);
            }
            if (s[i] == t[j]) {
 
                int ans = 1;
                if (i > 0 && j > 0) {
 
                    ans = 1 + dp[i - 1][j - 1];
                }
 
                // Update the maximum length
                dp[i][j] = max(dp[i][j], ans);
                r = max(r, dp[i][j]);
            }
        }
    }
 
    // Return the resulting length
    return (n - r);
}
 
// Driver Code
int main()
{
    // Given string s, t
    string s = "abcde";
    string t = "edacb";
 
    // Function Call
    cout << solve(s, t);
    return 0;
}


Java




// Java program for the above approach
class GFG{
    static int[][] dp = new int[1010][1010];
 
    // Function that finds the minimum number
    // of steps to find the minimum characters
    // must be moved to convert String s to t
    static int solve(String s, String t)
    {
        int n = s.length();
 
        // r = maximum value over all
        // dp[i][j] computed so far
        int r = 0;
 
        // dp[i][j] stores the longest
        // contiguous suffix of T[0..j]
        // that is subsequence of S[0..i]
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                dp[i][j] = 0;
                if (i > 0)
                {
                    dp[i][j] = Math.max(dp[i - 1][j],
                                        dp[i][j]);
                }
                if (s.charAt(i) == t.charAt(j))
                {
                    int ans = 1;
                    if (i > 0 && j > 0)
                    {
                        ans = 1 + dp[i - 1][j - 1];
                    }
 
                    // Update the maximum length
                    dp[i][j] = Math.max(dp[i][j], ans);
                    r = Math.max(r, dp[i][j]);
                }
            }
        }
 
        // Return the resulting length
        return (n - r);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // Given String s, t
        String s = "abcde";
        String t = "edacb";
 
        // Function Call
        System.out.print(solve(s, t));
    }
}
 
// This code is contributed by shikhasingrajput


Python3




# Python3 program for the above approach
dp = [[0] * 1010] * 1010
 
# Function that finds the minimum number
# of steps to find the minimum characters
# must be moved to convert string s to t
def solve(s, t):
 
    n = len(s)
 
    # r = maximum value over all
    # dp[i][j] computed so far
    r = 0
 
    # dp[i][j] stores the longest
    # contiguous suffix of T[0..j]
    # that is subsequence of S[0..i]
    for j in range(0, n):
        for i in range(0, n):
            dp[i][j] = 0
             
            if (i > 0):
                dp[i][j] = max(dp[i - 1][j],
                               dp[i][j])
             
            if (s[i] == t[j]):
                ans = 1
                if (i > 0 and j > 0):
                    ans = 1 + dp[i - 1][j - 1]
                 
                # Update the maximum length
                dp[i][j] = max(dp[i][j], ans)
                r = max(r, dp[i][j])
                 
    # Return the resulting length
    return (n - r)
 
# Driver Code
 
# Given string s, t
s = "abcde"
t = "edacb"
 
# Function call
print(solve(s, t))
 
# This code is contributed by code_hunt


C#




// C# program for the above approach
using System;
class GFG{
static int[, ] dp = new int[1010, 1010];
 
// Function that finds the minimum number
// of steps to find the minimum characters
// must be moved to convert String s to t
static int solve(String s, String t)
{
    int n = s.Length;
 
    // r = maximum value over all
    // dp[i, j] computed so far
    int r = 0;
 
    // dp[i, j] stores the longest
    // contiguous suffix of T[0..j]
    // that is subsequence of S[0..i]
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            dp[i, j] = 0;
            if (i > 0)
            {
                dp[i, j] = Math.Max(dp[i - 1, j],
                                    dp[i, j]);
            }
            if (s[i] == t[j])
            {
                int ans = 1;
                if (i > 0 && j > 0)
                {
                    ans = 1 + dp[i - 1, j - 1];
                }
 
                // Update the maximum length
                dp[i, j] = Math.Max(dp[i, j], ans);
                r = Math.Max(r, dp[i, j]);
            }
        }
    }
 
    // Return the resulting length
    return (n - r);
}
 
// Driver Code
public static void Main(String[] args)
{
        
    // Given String s, t
    String s = "abcde";
    String t = "edacb";
 
    // Function Call
    Console.Write(solve(s, t));
}
}
 
// This code is contributed by shikhasingrajput


Javascript




<script>
 
// Javascript program for the above approach
 
var dp = Array.from(Array(1010), ()=> Array(1010));
 
// Function that finds the minimum number
// of steps to find the minimum characters
// must be moved to convert string s to t
function solve(s, t)
{
 
    var n = s.length;
 
    // r = maximum value over all
    // dp[i][j] computed so far
    var r = 0;
 
    // dp[i][j] stores the longest
    // contiguous suffix of T[0..j]
    // that is subsequence of S[0..i]
    for (var i = 0; i < n; i++) {
 
        for (var j = 0; j < n; j++) {
 
            dp[i][j] = 0;
            if (i > 0) {
 
                dp[i][j] = Math.max(dp[i - 1][j],
                               dp[i][j]);
            }
            if (s[i] == t[j]) {
 
                var ans = 1;
                if (i > 0 && j > 0) {
 
                    ans = 1 + dp[i - 1][j - 1];
                }
 
                // Update the maximum length
                dp[i][j] = Math.max(dp[i][j], ans);
                r = Math.max(r, dp[i][j]);
            }
        }
    }
 
    // Return the resulting length
    return (n - r);
}
 
// Driver Code
// Given string s, t
var s = "abcde";
var t = "edacb";
// Function Call
document.write( solve(s, t));
 
</script>


Output

3

Time Complexity: O(N2), where N is the length of the given string
Auxiliary Space: O(N2)

Efficient approach :  Space optimization using 2 vectors 

 In this approach we use two vectors because in previous approach we can see that dp[i][j] is only dependent on the current row and previous row of dp.

dp[i][j] = max(dp[i – 1][j], dp[i][j]); 

Implementation Steps : 

  • Made 2 vectors says curr and prev that use to keep track of values of current and previous row of matrix respectively.
  • Now change dp[i] to curr and dp[i-1] to prev in previous approach.
  • After every iteration of outer loop store all values of curr to prev and move to the next iterations

Implementation :

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
 
 
// Function that finds the minimum number
// of steps to find the minimum characters
// must be moved to convert string s to t
int solve(string s, string t)
{
 
    int n = s.size();
     
    // vector made to track only 2 rows of 2d dp
    vector<int>prev(n+1);
    vector<int>curr(n+1);
     
    // r = maximum value over all
    // dp[i][j] computed so far
    int r = 0;
 
    // dp[i][j] stores the longest
    // contiguous suffix of T[0..j]
    // that is subsequence of S[0..i]
    for (int i = 0; i < n; i++) {
 
        for (int j = 0; j < n; j++) {
 
            curr[j] = 0;
            if (i > 0) {
 
                curr[j] = max(prev[j], curr[j]);
            }
            if (s[i] == t[j]) {
 
                int ans = 1;
                if (i > 0 && j > 0) {
 
                    ans = 1 + prev[j - 1];
                }
                 
                // Update the maximum length
                curr[j] = max(curr[j], ans);
                r = max(r, curr[j]);
            }
        }
        // store current row in previous row and do another iterations
        prev = curr;
    }
     
    // Return the resulting length
    return (n - r);
}
 
// Driver Code
int main()
{
    // Given string s, t
    string s = "abcde";
    string t = "edacb";
 
    // Function Call
    cout << solve(s, t);
    return 0;
}
 
// this code is contributed by bhardwajji


Java




// Java program for the above approach
 
import java.util.*;
 
public class Main {
     
    // Function that finds the minimum number
    // of steps to find the minimum characters
    // must be moved to convert string s to t
    static int solve(String s, String t) {
        int n = s.length();
        int[] prev = new int[n+1];
        int[] curr = new int[n+1];
        int r = 0;
 
        // dp[i][j] stores the longest contiguous suffix of T[0..j]
        // that is subsequence of S[0..i]
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                curr[j] = 0;
                if (i > 0) {
                    curr[j] = Math.max(prev[j], curr[j]);
                }
                if (s.charAt(i) == t.charAt(j)) {
                    int ans = 1;
                    if (i > 0 && j > 0) {
                        ans = 1 + prev[j - 1];
                    }
                    curr[j] = Math.max(curr[j], ans);
                    r = Math.max(r, curr[j]);
                }
            }
            // store current row in previous row and do another iterations
            prev = curr.clone();
        }
         
        // Return the resulting length
        return (n - r);
    }
     
    // Driver Code
    public static void main(String[] args) {
        // Given string s, t
        String s = "abcde";
        String t = "edacb";
         
        // Function Call
        System.out.println(solve(s, t));
    }
}
 
// Contributed by sdeadityasharma


Python3




# Function that finds the minimum number
# of steps to find the minimum characters
# must be moved to convert string s to t
def solve(s, t):
    n = len(s)
 
    # list made to track only 2 rows of 2d dp
    prev = [0] * (n + 1)
    curr = [0] * (n + 1)
 
    # r = maximum value over all
    # dp[i][j] computed so far
    r = 0
 
    # dp[i][j] stores the longest
    # contiguous suffix of T[0..j]
    # that is subsequence of S[0..i]
    for i in range(n):
        for j in range(n):
            curr[j] = 0
            if i > 0:
                curr[j] = max(prev[j], curr[j])
            if s[i] == t[j]:
                ans = 1
                if i > 0 and j > 0:
                    ans = 1 + prev[j - 1]
                 
                # Update the maximum length
                curr[j] = max(curr[j], ans)
                r = max(r, curr[j])
         
        # store current row in previous row and do another iterations
        prev = curr[:]
     
    # Return the resulting length
    return (n - r)
 
# Driver Code
if __name__ == '__main__':
    # Given string s, t
    s = "abcde"
    t = "edacb"
 
    # Function Call
    print(solve(s, t))


C#




using System;
 
public class MainClass {
    // Function that finds the minimum number
    // of steps to find the minimum characters
    // must be moved to convert string s to t
    static int Solve(string s, string t)
    {
        int n = s.Length;
        int[] prev = new int[n + 1];
        int[] curr = new int[n + 1];
        int r = 0;
 
        // dp[i][j] stores the longest contiguous suffix of
        // T[0..j] that is subsequence of S[0..i]
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                curr[j] = 0;
                if (i > 0) {
                    curr[j] = Math.Max(prev[j], curr[j]);
                }
                if (s[i] == t[j]) {
                    int ans = 1;
                    if (i > 0 && j > 0) {
                        ans = 1 + prev[j - 1];
                    }
                    curr[j] = Math.Max(curr[j], ans);
                    r = Math.Max(r, curr[j]);
                }
            }
            // store current row in previous row and do
            // another iterations
            prev = (int[])curr.Clone();
        }
 
        // Return the resulting length
        return (n - r);
    }
 
    // Driver Code
    public static void Main(string[] args)
    {
        // Given string s, t
        string s = "abcde";
        string t = "edacb";
 
        // Function Call
        Console.WriteLine(Solve(s, t));
    }
}
// This code is contributed by user_dtewbxkn77n


Javascript




// Javascript program for the above approach
 
// Function that finds the minimum number
// of steps to find the minimum characters
// must be moved to convert string s to t
function solve(s, t) {
  const n = s.length;
  let prev = new Array(n + 1).fill(0);
  let curr = new Array(n + 1).fill(0);
  let r = 0;
 
  // dp[i][j] stores the longest contiguous suffix of T[0..j]
  // that is subsequence of S[0..i]
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      curr[j] = 0;
      if (i > 0) {
        curr[j] = Math.max(prev[j], curr[j]);
      }
      if (s.charAt(i) == t.charAt(j)) {
        let ans = 1;
        if (i > 0 && j > 0) {
          ans = 1 + prev[j - 1];
        }
        curr[j] = Math.max(curr[j], ans);
        r = Math.max(r, curr[j]);
      }
    }
    // store current row in previous row and do another iterations
    prev = curr.slice();
  }
 
  // Return the resulting length
  return n - r;
}
 
// Driver Code
const s = "abcde";
const t = "edacb";
 
// Function Call
console.log(solve(s, t));


Output

3

Time Complexity: O(N2), where N is the length of the given string
Auxiliary Space: O(N) only use 1d vector not 2d matrix to store values.

Note: The above naive approach is efficient for smaller strings whereas, the above efficient approach is efficient for larger strings.
 



Last Updated : 06 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads