Welcome to Subscribe On Youtube

1208. Get Equal Substrings Within Budget

Description

You are given two strings s and t of the same length and an integer maxCost.

You want to change s to t. Changing the ith character of s to ith character of t costs |s[i] - t[i]| (i.e., the absolute difference between the ASCII values of the characters).

Return the maximum length of a substring of s that can be changed to be the same as the corresponding substring of t with a cost less than or equal to maxCost. If there is no substring from s that can be changed to its corresponding substring from t, return 0.

 

Example 1:

Input: s = "abcd", t = "bcdf", maxCost = 3
Output: 3
Explanation: "abc" of s can change to "bcd".
That costs 3, so the maximum length is 3.

Example 2:

Input: s = "abcd", t = "cdef", maxCost = 3
Output: 1
Explanation: Each character in s costs 2 to change to character in t,  so the maximum length is 1.

Example 3:

Input: s = "abcd", t = "acde", maxCost = 0
Output: 1
Explanation: You cannot make any change, so the maximum length is 1.

 

Constraints:

  • 1 <= s.length <= 105
  • t.length == s.length
  • 0 <= maxCost <= 106
  • s and t consist of only lowercase English letters.

Solutions

Solution 1: Prefix Sum + Binary Search

We can create an array f of length n+1, where f[i] represents the sum of the absolute differences of ASCII values between the first i characters of string s and the first i characters of string t. Thus, we can calculate the sum of the absolute differences of ASCII values from the i-th character to the j-th character of string s by f[j+1]f[i], where 0ij<n.

Note that the length has monotonicity, i.e., if there exists a substring of length x that satisfies the condition, then a substring of length x1 must also satisfy the condition. Therefore, we can use binary search to find the maximum length.

We define a function check(x), which indicates whether there exists a substring of length x that satisfies the condition. In this function, we only need to enumerate all substrings of length x and check whether they satisfy the condition. If there exists a substring that satisfies the condition, the function returns true, otherwise it returns false.

Next, we define the left boundary l of binary search as 0 and the right boundary r as n. In each step, we let mid=l+r+12. If the return value of check(mid) is true, we update the left boundary to mid, otherwise we update the right boundary to mid1. After the binary search, the left boundary we get is the answer.

The time complexity is O(n×logn), and the space complexity is O(n). Here, n is the length of string s.

Solution 2: Two Pointers

We can maintain two pointers j and i, initially i=j=0; maintain a variable sum, representing the sum of the absolute differences of ASCII values in the index interval [i,..j]. In each step, we move i to the right by one position, then update $sum = sum + s[i] - t[i] .Ifsum \gt maxCost,thenwemovethepointerjtotherightinaloop,andcontinuouslyreducethevalueofsumduringthemovingprocessuntilsum \leq maxCost.Thenweupdatetheanswer,i.e.,ans = \max(ans, i - j + 1)$.

Finally, return the answer.

The time complexity is O(n), and the space complexity is O(1). Here, n is the length of string s.

  • class Solution {
        private int maxCost;
        private int[] f;
        private int n;
    
        public int equalSubstring(String s, String t, int maxCost) {
            n = s.length();
            f = new int[n + 1];
            this.maxCost = maxCost;
            for (int i = 0; i < n; ++i) {
                int x = Math.abs(s.charAt(i) - t.charAt(i));
                f[i + 1] = f[i] + x;
            }
            int l = 0, r = n;
            while (l < r) {
                int mid = (l + r + 1) >>> 1;
                if (check(mid)) {
                    l = mid;
                } else {
                    r = mid - 1;
                }
            }
            return l;
        }
    
        private boolean check(int x) {
            for (int i = 0; i + x - 1 < n; ++i) {
                int j = i + x - 1;
                if (f[j + 1] - f[i] <= maxCost) {
                    return true;
                }
            }
            return false;
        }
    }
    
  • class Solution {
    public:
        int equalSubstring(string s, string t, int maxCost) {
            int n = s.size();
            int f[n + 1];
            f[0] = 0;
            for (int i = 0; i < n; ++i) {
                f[i + 1] = f[i] + abs(s[i] - t[i]);
            }
            auto check = [&](int x) -> bool {
                for (int i = 0; i + x - 1 < n; ++i) {
                    int j = i + x - 1;
                    if (f[j + 1] - f[i] <= maxCost) {
                        return true;
                    }
                }
                return false;
            };
            int l = 0, r = n;
            while (l < r) {
                int mid = (l + r + 1) >> 1;
                if (check(mid)) {
                    l = mid;
                } else {
                    r = mid - 1;
                }
            }
            return l;
        }
    };
    
  • class Solution:
        def equalSubstring(self, s: str, t: str, maxCost: int) -> int:
            def check(x):
                for i in range(n):
                    j = i + mid - 1
                    if j < n and f[j + 1] - f[i] <= maxCost:
                        return True
                return False
    
            n = len(s)
            f = list(accumulate((abs(ord(a) - ord(b)) for a, b in zip(s, t)), initial=0))
            l, r = 0, n
            while l < r:
                mid = (l + r + 1) >> 1
                if check(mid):
                    l = mid
                else:
                    r = mid - 1
            return l
    
    
  • func equalSubstring(s string, t string, maxCost int) int {
    	n := len(s)
    	f := make([]int, n+1)
    	for i, a := range s {
    		f[i+1] = f[i] + abs(int(a)-int(t[i]))
    	}
    	check := func(x int) bool {
    		for i := 0; i+x-1 < n; i++ {
    			if f[i+x]-f[i] <= maxCost {
    				return true
    			}
    		}
    		return false
    	}
    	l, r := 0, n
    	for l < r {
    		mid := (l + r + 1) >> 1
    		if check(mid) {
    			l = mid
    		} else {
    			r = mid - 1
    		}
    	}
    	return l
    }
    
    func abs(x int) int {
    	if x < 0 {
    		return -x
    	}
    	return x
    }
    
  • function equalSubstring(s: string, t: string, maxCost: number): number {
        const n = s.length;
        const f = Array(n + 1).fill(0);
    
        for (let i = 0; i < n; i++) {
            f[i + 1] = f[i] + Math.abs(s.charCodeAt(i) - t.charCodeAt(i));
        }
    
        const check = (x: number): boolean => {
            for (let i = 0; i + x - 1 < n; i++) {
                if (f[i + x] - f[i] <= maxCost) {
                    return true;
                }
            }
            return false;
        };
    
        let l = 0,
            r = n;
        while (l < r) {
            const mid = (l + r + 1) >> 1;
            if (check(mid)) {
                l = mid;
            } else {
                r = mid - 1;
            }
        }
    
        return l;
    }
    
    

All Problems

All Solutions