Minimum Cost To Make Two Strings Identical

Last Updated : 21 Jul, 2026

Given two strings s1 and s2, and two integers costS1 and costS2, representing the cost of deleting one character from s1 and s2 respectively, find the minimum cost required to make both strings identical. You can delete any number of characters from either string.

Examples : 

Input: s1 = "abcd", s2 = "acdb", costS1 = 10, costS2 = 20
Output: 30
Explanation: Delete 'b' from both strings to obtain "acd". The total cost is 10 + 20 = 30.

Input: s1 = "ef", s2 = "gh", costS1 = 10, costS2 = 20
Output: 60
Explanation: The two strings have no common characters, so delete all characters from both strings. The total cost is (2 × 10) + (2 × 20) = 60.

Try It Yourself
redirect icon

[Naive Approach] Using Recursion - O(2^(n + m)) Time and O(n + m) Space

The idea is to first find the length of the Longest Common Subsequence (LCS) of the two strings using recursion. If the current characters match, they must be part of the LCS, so we move to the next characters in both strings. Otherwise, we try skipping one character from either string and take the maximum LCS length obtained. Once the LCS length is known, the minimum deletion cost is obtained by deleting all characters that are not part of the LCS.

Step by Step Implementation:

  • Define a recursive function to compute the LCS length starting from given indices in both strings.
  • If the current characters are equal, include them in the LCS and recursively process the remaining strings.
  • Otherwise, recursively skip one character from either string and take the maximum LCS length.
  • Let the computed LCS length be lcsLength.
  • Return (s1.length() - lcsLength) * costS1 + (s2.length() - lcsLength) * costS2.
C++
#include <iostream>
#include <string>
using namespace std;

int lcs(string& s1, string& s2, int i, int j) {
    if (i == s1.length() || j == s2.length())
        return 0;

    if (s1[i] == s2[j])
        return 1 + lcs(s1, s2, i + 1, j + 1);

    return max(lcs(s1, s2, i + 1, j),
               lcs(s1, s2, i, j + 1));
}

int findMinCost(string& s1, string& s2, int costS1, int costS2) {
    int lcsLength = lcs(s1, s2, 0, 0);

    return (s1.length() - lcsLength) * costS1 +
           (s2.length() - lcsLength) * costS2;
}

int main() {
    string s1 = "abcd", s2 = "acdb";
    int costS1 = 10, costS2 = 20;

    cout << findMinCost(s1, s2, costS1, costS2);

    return 0;
}
Java
public class GFG {
    public static int lcs(String s1, String s2, int i, int j) {
        if (i == s1.length() || j == s2.length())
            return 0;

        if (s1.charAt(i) == s2.charAt(j))
            return 1 + lcs(s1, s2, i + 1, j + 1);

        return Math.max(lcs(s1, s2, i + 1, j),
                        lcs(s1, s2, i, j + 1));
    }

    public static int findMinCost(String s1, String s2, int costS1, int costS2) {
        int lcsLength = lcs(s1, s2, 0, 0);

        return (s1.length() - lcsLength) * costS1 +
               (s2.length() - lcsLength) * costS2;
    }

    public static void main(String[] args) {
        String s1 = "abcd";
        String s2 = "acdb";
        int costS1 = 10;
        int costS2 = 20;

        System.out.println(findMinCost(s1, s2, costS1, costS2));
    }
}
Python
def lcs(s1, s2, i, j):
    if i == len(s1) or j == len(s2):
        return 0

    if s1[i] == s2[j]:
        return 1 + lcs(s1, s2, i + 1, j + 1)

    return max(lcs(s1, s2, i + 1, j),
               lcs(s1, s2, i, j + 1))


def findMinCost(s1, s2, costS1, costS2):
    lcsLength = lcs(s1, s2, 0, 0)

    return ((len(s1) - lcsLength) * costS1 +
            (len(s2) - lcsLength) * costS2)

if __name__ == "__main__":
    s1 = "abcd"
    s2 = "acdb"
    costS1 = 10
    costS2 = 20
    
    print(findMinCost(s1, s2, costS1, costS2))
C#
using System;

class GFG {
    public static int Lcs(string s1, string s2, int i, int j) {
        if (i == s1.Length || j == s2.Length)
            return 0;

        if (s1[i] == s2[j])
            return 1 + Lcs(s1, s2, i + 1, j + 1);

        return Math.Max(Lcs(s1, s2, i + 1, j),
                        Lcs(s1, s2, i, j + 1));
    }

    public static int FindMinCost(string s1, string s2, int costS1, int costS2) {
        int lcsLength = Lcs(s1, s2, 0, 0);

        return (s1.Length - lcsLength) * costS1 +
               (s2.Length - lcsLength) * costS2;
    }

    static void Main() {
        string s1 = "abcd";
        string s2 = "acdb";
        int costS1 = 10;
        int costS2 = 20;

        Console.WriteLine(FindMinCost(s1, s2, costS1, costS2));
    }
}
JavaScript
function lcs(s1, s2, i, j) {
    if (i === s1.length || j === s2.length)
        return 0;

    if (s1[i] === s2[j])
        return 1 + lcs(s1, s2, i + 1, j + 1);

    return Math.max(
        lcs(s1, s2, i + 1, j),
        lcs(s1, s2, i, j + 1)
    );
}

function findMinCost(s1, s2, costS1, costS2) {
    const lcsLength = lcs(s1, s2, 0, 0);

    return (s1.length - lcsLength) * costS1 +
           (s2.length - lcsLength) * costS2;
}

// Driver Code
const s1 = "abcd";
const s2 = "acdb";
const costS1 = 10;
const costS2 = 20;

console.log(findMinCost(s1, s2, costS1, costS2));

Output
30

[Expected Approach] Using Space Optimized Dynamic Programming - O(n * m) Time and O(min(n, m)) Space

The idea is to compute the Longest Common Subsequence (LCS) of the two strings using dynamic programming. Since each DP state depends only on the previous row and the current row, storing the entire DP table is unnecessary. Instead, we keep only two 1D arrays, reducing the space complexity from O(n * m) to O(min(n, m)). Once the LCS length is obtained, the minimum deletion cost is calculated by removing all characters that are not part of the LCS.

Step by Step Implementation:

  • Let the shorter string determine the DP array size to minimize space usage.
  • Create two arrays prev and curr of size m + 1, where m is the length of the shorter string.
  • Iterate through both strings and compute the LCS length using the DP recurrence.
  • After processing each row, swap the two arrays.
  • Let the computed LCS length be lcsLength.
  • Return (s1.length() - lcsLength) * costS1 + (s2.length() - lcsLength) * costS2.
C++
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int findMinCost(string& s1, string& s2, int costS1, int costS2) {
    
    // Ensure the shorter string determines the DP array size.
    if (s1.length() < s2.length()) {
        swap(s1, s2);
        swap(costS1, costS2);
    }

    int n = s1.length(), m = s2.length();
    vector<int> prev(m + 1), curr(m + 1);

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (s1[i - 1] == s2[j - 1])
                curr[j] = prev[j - 1] + 1;
            else
                curr[j] = max(prev[j], curr[j - 1]);
        }

        // Reuse the current row as the previous row for the next iteration.
        swap(prev, curr);
    }

    int lcsLength = prev[m];

    return (n - lcsLength) * costS1 +
           (m - lcsLength) * costS2;
}

int main() {
    string s1 = "abcd", s2 = "acdb";
    int costS1 = 10, costS2 = 20;

    cout << findMinCost(s1, s2, costS1, costS2);

    return 0;
}
Java
public class GFG {
    public static int findMinCost(String s1, String s2, int costS1, int costS2) {
        
        // Ensure the shorter string determines the DP array size.
        if (s1.length() < s2.length()) {
            String temp = s1;
            s1 = s2;
            s2 = temp;

            int cost = costS1;
            costS1 = costS2;
            costS2 = cost;
        }

        int n = s1.length(), m = s2.length();
        int[] prev = new int[m + 1];
        int[] curr = new int[m + 1];

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (s1.charAt(i - 1) == s2.charAt(j - 1))
                    curr[j] = prev[j - 1] + 1;
                else
                    curr[j] = Math.max(prev[j], curr[j - 1]);
            }

            // Reuse the current row as the previous row for the next iteration.
            int[] temp = prev;
            prev = curr;
            curr = temp;
        }

        int lcsLength = prev[m];

        return (n - lcsLength) * costS1 +
               (m - lcsLength) * costS2;
    }

    public static void main(String[] args) {
        String s1 = "abcd";
        String s2 = "acdb";
        int costS1 = 10;
        int costS2 = 20;

        System.out.println(findMinCost(s1, s2, costS1, costS2));
    }
}
Python
def findMinCost(s1, s2, costS1, costS2):
    
    # Ensure the shorter string determines the DP array size.
    if len(s1) < len(s2):
        s1, s2 = s2, s1
        costS1, costS2 = costS2, costS1

    n, m = len(s1), len(s2)
    prev = [0] * (m + 1)
    curr = [0] * (m + 1)

    for i in range(1, n + 1):
        for j in range(1, m + 1):
            if s1[i - 1] == s2[j - 1]:
                curr[j] = prev[j - 1] + 1
            else:
                curr[j] = max(prev[j], curr[j - 1])

        # Reuse the current row as the previous row for the next iteration.
        prev, curr = curr, prev

    lcsLength = prev[m]

    return ((n - lcsLength) * costS1 +
            (m - lcsLength) * costS2)

if __name__ == "__main__":
    s1 = "abcd"
    s2 = "acdb"
    costS1 = 10
    costS2 = 20
    
    print(findMinCost(s1, s2, costS1, costS2))
C#
using System;

class GFG {
    public static int findMinCost(string s1, string s2, int costS1, int costS2) {
        
        // Ensure the shorter string determines the DP array size.
        if (s1.Length < s2.Length) {
            (s1, s2) = (s2, s1);
            (costS1, costS2) = (costS2, costS1);
        }

        int n = s1.Length, m = s2.Length;
        int[] prev = new int[m + 1];
        int[] curr = new int[m + 1];

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (s1[i - 1] == s2[j - 1])
                    curr[j] = prev[j - 1] + 1;
                else
                    curr[j] = Math.Max(prev[j], curr[j - 1]);
            }

            // Reuse the current row as the previous row for the next iteration.
            int[] temp = prev;
            prev = curr;
            curr = temp;
        }

        int lcsLength = prev[m];

        return (n - lcsLength) * costS1 +
               (m - lcsLength) * costS2;
    }

    static void Main() {
        string s1 = "abcd";
        string s2 = "acdb";
        int costS1 = 10;
        int costS2 = 20;

        Console.WriteLine(findMinCost(s1, s2, costS1, costS2));
    }
}
JavaScript
function findMinCost(s1, s2, costS1, costS2) {
    
    // Ensure the shorter string determines the DP array size.
    if (s1.length < s2.length) {
        [s1, s2] = [s2, s1];
        [costS1, costS2] = [costS2, costS1];
    }

    const n = s1.length;
    const m = s2.length;

    let prev = new Array(m + 1).fill(0);
    let curr = new Array(m + 1).fill(0);

    for (let i = 1; i <= n; i++) {
        for (let j = 1; j <= m; j++) {
            if (s1[i - 1] === s2[j - 1])
                curr[j] = prev[j - 1] + 1;
            else
                curr[j] = Math.max(prev[j], curr[j - 1]);
        }

        // Reuse the current row as the previous row for the next iteration.
        [prev, curr] = [curr, prev];
    }

    const lcsLength = prev[m];

    return (n - lcsLength) * costS1 +
           (m - lcsLength) * costS2;
}

// Driver Code
const s1 = "abcd";
const s2 = "acdb";
const costS1 = 10;
const costS2 = 20;

console.log(findMinCost(s1, s2, costS1, costS2));

Output
30
Comment