[LeetCode] 208.予算内で等しい部分文字列を取得する(C ++)


件名のソース:https//leetcode-cn.com/problems/get-equal-substrings-within-budget/

タイトル説明

同じ長さの2つの文字列sとtを与えます。
sのi番目の文字をtのi番目の文字に変更するには| s [i] -t [i] |のオーバーヘッドが必要です(オーバーヘッドは0の場合があります)。これは、ASCIIコード値の違いです。 2文字の絶対値。

文字列を変更するための最大予算はmaxCostです。文字列を変換する場合、総コストは予算以下である必要があります。これは、文字列の変換が完了しない可能性があることも意味します。

sの部分文字列をtの対応する部分文字列に変換できる場合は、変換できる最大長を返します。

sに、tの対応する部分文字列に変換できる部分文字列がない場合、0が返されます。

示例 1:

输入:s = "abcd", t = "bcdf", cost = 3
输出:3
解释:s 中的 "abc" 可以变为 "bcd"。开销为 3,所以最大长度为 3。
示例 2:

输入:s = "abcd", t = "cdef", cost = 3
输出:1
解释:s 中的任一字符要想变成 t 中对应的字符,其开销都是 2。因此,最大长度为 1。
示例 3:

输入:s = "abcd", t = "acde", cost = 0
输出:1
解释:你无法作出任何改动,所以最大长度为 1。

提示:

1 <= s.length, t.length <= 10^5
0 <= maxCost <= 10^6
s 和 t 都只含小写英文字母。

一般的なアイデア

  • 2つの文字列が与えられた場合、文字列内の文字をt(文字間の距離の絶対値)の対応する位置の文字に変換し、コストを与えて、変換できる最長の部分文字列の長さを見つけます

スライディングウィンドウ+デュアルポインター

  • 文字間の距離はdif配列に格納され、スライディングウィンドウの右側のウィンドウがループ変数として使用されます。現在の文字を変更する必要がある場合は、現在の使用済みカウントが合計されます。今回は徐々に左ウィンドウを移動し、この時点で最長のウィンドウ長を更新します
const int MAXN = 1e5 + 1;
int diff[MAXN];
class Solution {
    
    
public:
    int equalSubstring(string s, string t, int maxCost) {
    
    
        int left = 0, right = 0, ans = 0;
        int len = s.length();
        memset(diff, 0, sizeof(diff));
        for(int i = 0 ; i < len ; ++i)  diff[i] = abs(s[i] - t[i]);
        int curCost = 0;
        for(; right < len ; ++right){
    
    
            curCost += diff[right];
            while(curCost > maxCost){
    
    
                curCost -= diff[left];
                ++left;
            }
            ans = max(ans, right - left + 1);
        }
        return ans;
    }
};

複雑さの分析

  • 時間計算量:O(n)。nは配列の長さであり、左右両方がn回スライドしていると見なすことができます。
  • スペースの複雑さ:O(n)。nは配列の長さです

プレフィックスと+二分探索

  • 文字間の距離が格納されている配列はすべて正の数であるため、これは、接頭辞の合計のアイデアを使用して単調に増加するシーケンスを生成するように促し、バイナリ検索を直接実行できるようにします。O(logn)は最後を見つけます次の条件を満たすもの番号、および最長のウィンドウ長の合計を更新します
    [バウンド]-バウンド[右-1]> =ターゲット合計[バウンド]-バウンド[右-1]> =ターゲットs u m s [ b o u n d ]b o u n d [ r i g h t1 ]>>=t a r g e t
class Solution {
    
    
public:
    int equalSubstring(string s, string t, int maxCost) {
    
    
        int left = 0, ans = 0, len = s.length();
        int nums[len + 1];
        memset(nums, 0, sizeof(nums));
        for(int i = 1 ; i <= len ; ++i)  nums[i] = nums[i - 1] + abs(s[i - 1] - t[i - 1]);
        for(int right = 1; right <= len ; ++right){
    
    
            int target = nums[right - 1] + maxCost;
            int index = BinarySearch(target, nums, 0, len);
            ans = max(ans, index - right + 1);
        }
        return ans;
    }
    int BinarySearch(int target, int* nums,int left, int right){
    
    
        int len = right;
        while(left <= right){
    
    
            int mid = right + ((left - right) >> 1);
            if(nums[mid] > target)  right = mid - 1;
            else{
    
    
                if(mid == len || nums[mid + 1]  > target) return mid;
                else left = mid + 1;
            }
        }
        return -1;
    }
};

複雑さの分析

  • 時間計算量:O(nlogn)。nは配列の長さ、nサイクル* lognはバイナリ検索の時間計算量です
  • スペースの複雑さ:O(n)。nは配列の長さです

おすすめ

転載: blog.csdn.net/lr_shadow/article/details/114000522