Longest equal substrings with cost less than K

Last Updated : 9 May, 2026

Given two strings s1 and s2 of the same length, which consist of lowercase letters and also an integer k. The task is to find the maximum length up to which s1 can be changed to s2 within the given cost k
The cost of changing a character is given by the absolute difference between the ASCII value of the characters. That is, to change a character at index i, cost = |s1[i] - s2[i]|

Examples: 

Input: s1 = abcd, s2 = bcde, k = 3 
Output:
Explanation: The first three characters can be changed with cost = 1 + 1 + 1.  

Input: s1 = "xyzabcd", s2 = "bcdfxyw", k = 5
Output: 4
Explanation : abcd can be changed to match bcdf because the total cost to change these characters is 1 + 1 + 1 + 2 = 5, which is within k.

Input: s1 = "abcd", s2 = "cdef", k = 3
Output: 1
Explanation: A maximum of 1 character can be changed because the cost to change each character is 2, and taking more than one character would exceed the total cost K.

[Better Approach] Using Prefix Sum + Two Pointers – O(n) Time and O(n) Space

This approach uses a prefix sum array to store the cumulative cost of converting s1 to s2. Then, using a two-pointer technique, we find the longest substring whose cost does not exceed k.
The prefix array helps in calculating the cost of any substring in O(1) time.

  • Maintain two pointers, say i and j.
  • In a while loop, check if the difference between ith index and jth index of prefix array is greater than given cost or not.
  • If the difference is greater than the given cost, then increase the j pointer to compensate for the cost, else increase the i pointer.


Below is the implementation of the above approach:

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

// Function to find the maximum length
int maxLen(string s1, string s2, int K)
{
    int n = s1.size();
    
    vector<int> prefix(n + 1, 0);
    int sol = 0;

    // Build prefix sum of cost
    for (int i = 1; i <= n; i++) {
        prefix[i] = prefix[i - 1] + abs(s1[i - 1] - s2[i - 1]);
    }

    int j = 0;

    for (int i = 1; i <= n; i++) {
        while ((prefix[i] - prefix[j]) > K) {
            j++;
        }
        sol = max(sol, i - j);
    }

    return sol;
}

// Driver code
int main()
{
    string s1 = "abcd";
    string s2 = "bcde";
    int K = 3;

    cout << maxLen(s1, s2, K) << "\n";

    return 0;
}
Java
class GFG
{

// Function to find the maximum length
static int maxLen(String s1, String s2, int K)
{
    int n = s1.length();

    int[] prefix = new int[n + 1];
    int sol = 0;

    // Build prefix cost array
    for (int i = 1; i <= n; i++) 
    {
        prefix[i] = prefix[i - 1] + 
            Math.abs(s1.charAt(i - 1) - s2.charAt(i - 1));
    }

    int j = 0;

    for (int i = 1; i <= n; i++)
    {
        while ((prefix[i] - prefix[j]) > K)
        {
            j++;
        }

        // Update maximum length
        sol = Math.max(sol, i - j);
    }

    return sol;
}

// Driver code
public static void main(String[] args)
{
    String s1 = "abcd", s2 = "bcde";
    int K = 3;

    System.out.print(maxLen(s1, s2, K));
}
}
Python
# Function to find the maximum length
def maxLen(s1, s2, K):
    n = len(s1)
    
    prefix = [0] * (n + 1)
    sol = 0

    # Build prefix cost array
    for i in range(1, n + 1):
        prefix[i] = prefix[i - 1] + abs(ord(s1[i - 1]) - ord(s2[i - 1]))

    j = 0

    for i in range(1, n + 1):
        while (prefix[i] - prefix[j]) > K:
            j += 1

        sol = max(sol, i - j)

    return sol


# Driver code
s1 = "abcd"
s2 = "bcde"
K = 3

print(maxLen(s1, s2, K))
C#
// C# program to find the 
// maximum length of equal subString 
// within a given cost 
using System;

class GFG 
{ 
    
    // Function to find the maximum length 
    static int maxLen(string X, string Y, 
                    int N, int K) 
    { 
    
        int []count = new int[N + 1]; 
        int sol = 0; 
        count[0] = 0; 
    
        // Fill the prefix array with 
        // the difference of letters 
        for (int i = 1; i <= N; i++) 
        { 
    
            count[i] = count[i - 1] + 
                    Math.Abs(X[i - 1] - 
                    Y[i - 1]); 
        } 
    
        int j = 0; 
    
        for (int i = 1; i <= N; i++) 
        { 
            while ((count[i] - count[j]) > K) 
            { 
                j++; 
            } 
    
            // Update the maximum length 
            sol = Math.Max(sol, i - j); 
        } 
    
        return sol; 
    } 

    // Driver code 
    public static void Main() 
    { 
    
        int N = 4; 
        string X = "abcd", Y = "bcde"; 
        int K = 3; 
    
        Console.WriteLine(maxLen(X, Y, N, K) + "\n"); 
    } 
} 
JavaScript
// Function to find the maximum length 
function maxLen(s1, s2, K) 
{ 
    let n = s1.length;

    let prefix = new Array(n + 1).fill(0);
    let sol = 0;

    for (let i = 1; i <= n; i++) 
    { 
        prefix[i] = prefix[i - 1] + 
            Math.abs(s1[i - 1].charCodeAt(0) - 
                     s2[i - 1].charCodeAt(0)); 
    } 
      
    let j = 0; 
      
    for (let i = 1; i <= n; i++) 
    { 
        while ((prefix[i] - prefix[j]) > K) 
        { 
            j++; 
        } 
      
        sol = Math.max(sol, i - j); 
    } 
      
    return sol; 
}

// Driver code
let s1 = "abcd";
let s2 = "bcde";
let K = 3;

console.log(maxLen(s1, s2, K));

Output
3

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

[Expected Approach] Using Sliding Window – O(n) Time and O(1) Space

This approach uses the sliding window technique to find the maximum length of a substring such that the total cost of converting s1 to s2 does not exceed k. We maintain a window with two pointers and keep track of the current cost. If the cost exceeds k, we shrink the window from the left until it becomes valid again

  1.  We maintain a sliding window of length len that starts at index 0 and ends at index i.
  2.  We calculate the total cost of changing the characters within this window and compare it with the given cost k.
  3.  If the total cost is less than or equal to k, we update the maximum length seen so far. If the total cost is greater than k, we shrink the window from the left to decrease the cost until it becomes less than or equal to k.
  4. To calculate the cost of changing the characters at each index i, we use the absolute difference between the ASCII value of the characters.
  5. Hence we return the maxlen as our Output.

Implementation:

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

// Function to find the maximum length
int maxLen(string s1, string s2, int K) {
    int n = s1.size();
    int cost = 0, len = 0, maxlen = 0;

    for (int i = 0; i < n; i++) {
        cost += abs(s1[i] - s2[i]); // add cost
        len++;

        while (cost > K) { // shrink window
            cost -= abs(s1[i - len + 1] - s2[i - len + 1]);
            len--;
        }

        maxlen = max(maxlen, len);
    }

    return maxlen;
}

int main() {
    string s1 = "abcd", s2 = "bcde";
    int K = 3;

    int result = maxLen(s1, s2, K);
    cout << result << "\n";

    return 0;
}
Java
import java.util.*;

public class GFG {
    
    // Function to find the maximum length
    public static int maxLen(String s1, String s2, int K) {
        int n = s1.length();
        int cost = 0, len = 0, maxlen = 0;

        for (int i = 0; i < n; i++) {
            cost += Math.abs(s1.charAt(i) - s2.charAt(i));
            len++;

            while (cost > K) {
                cost -= Math.abs(s1.charAt(i - len + 1) - s2.charAt(i - len + 1));
                len--;
            }

            maxlen = Math.max(maxlen, len);
        }

        return maxlen;
    }

    public static void main(String[] args) {
        String s1 = "abcd";
        String s2 = "bcde";
        int K = 3;

        int result = maxLen(s1, s2, K);
        System.out.println(result);
    }
}
Python
# Function to find the maximum length
def maxLen(s1, s2, K):
    n = len(s1)
    cost = 0
    length = 0
    maxlen = 0

    for i in range(n):
        cost += abs(ord(s1[i]) - ord(s2[i]))
        length += 1

        while cost > K:
            cost -= abs(ord(s1[i - length + 1]) - ord(s2[i - length + 1]))
            length -= 1

        maxlen = max(maxlen, length)

    return maxlen


def main():
    s1 = "abcd"
    s2 = "bcde"
    K = 3

    result = maxLen(s1, s2, K)
    print(result)


if __name__ == "__main__":
    main()
C#
using System;

class GFG {
    // Function to find the maximum length
    static int maxLen(string s1, string s2, int K)
    {
        int n = s1.Length;
        int cost = 0, len = 0, maxlen = 0;

        for (int i = 0; i < n; i++) {
            cost += Math.Abs(s1[i] - s2[i]);
            len++;

            while (cost > K) {
                cost -= Math.Abs(s1[i - len + 1] - s2[i - len + 1]);
                len--;
            }

            maxlen = Math.Max(maxlen, len);
        }

        return maxlen;
    }

    static void Main(string[] args)
    {
        string s1 = "abcd", s2 = "bcde";
        int K = 3;

        int result = maxLen(s1, s2, K);
        Console.WriteLine(result);
    }
}
JavaScript
// Function to find the maximum length
function maxLen(s1, s2, K) {
  const n = s1.length;

  let cost = 0;
  let len = 0;
  let maxlen = 0;

  for (let i = 0; i < n; i++) {
    cost += Math.abs(s1.charCodeAt(i) - s2.charCodeAt(i));
    len++;

    while (cost > K) {
      cost -= Math.abs(s1.charCodeAt(i - len + 1) - s2.charCodeAt(i - len + 1));
      len--;
    }

    maxlen = Math.max(maxlen, len);
  }

  return maxlen;
}

// Example usage:
const s1 = "abcd";
const s2 = "bcde";
const K = 3;

const result = maxLen(s1, s2, K);
console.log(result);

Output
3
Comment