首页 > 其他分享 >395. 至少有 K 个重复字符的最长子串 (滑动窗口) 是真的难,没一天功夫,根部写不了

395. 至少有 K 个重复字符的最长子串 (滑动窗口) 是真的难,没一天功夫,根部写不了

时间:2022-12-25 17:47:34浏览次数:41  
标签:子串 字符 right 窗口 res 395 滑动 lgst left

class Solution { public:     int longestSubstring(string s, int k) {         int res_left = 0, res_right = 0;         for(int t = 1;t <= 26; t++){//分成26种情况讨论             int left=0,right = 0;  // 窗口边界             int lgst_left=0,lgst_right = 0; // 当前情况下的最好窗口边界             int total = 0; // 窗口中已有字符的种数             int less = 0;  //出现的次数小于k次的字符的种数             int cnt[26] = {0}; //每种字符出现的次数             while(right < s.size()){ // 窗口右边界没有出界时                 while(total <= t && right < s.size()){ // 窗口右边界右移到窗口中含有t种字符为止                     if(cnt[s[right]-'a'] == 0){  // 某个字符在窗口中的出现次数是0,是新进到窗口中                         if(total != t){  // 并且这个时候窗口还可以新进字符                             total++;  // 窗口中的字符种数加1                             less++;   // 少于k次的字符种数也加1                             cnt[s[right]-'a']++;                             if(cnt[s[right] - 'a'] == k) //如果k==1的话,那么少于k次的字符种数减1                             {                                 less--;                             }                         }else{       //当窗口不可以新进字符了,窗口右边界结束                             break;                         }                     }else{   //右边的字符是一个已经在窗口中有的字符,更新窗口的属性                         cnt[s[right]-'a']++;                         if(cnt[s[right] - 'a'] == k) // 一个字符在窗口中出现次数达到k次,少于k次的字符种数减1。                         {                             less--;                         }                     }                     right++;  //窗口右界向右移一位                 }                 // 判断该窗口子串是否满足每一个字符出现的次数都不少于k,并且记录最长的子串                 if(!less&& right - 1 - left > lgst_right - lgst_left) {                     lgst_left = left;                     lgst_right = right - 1;  //right 属于窗口的下一个位置                 }                 //移动窗口左边界,使尝试找出下一个窗口。                 while(total == t){ //窗口中的字符种数是t 就右移,直到窗口中的字符种数不为t.                     if(cnt[s[left]-'a'] == k){ // 窗口左界右移时,某一字符数出现次数等于k,那么马上会少于k,所以 少于k次的字符数加1                         less++;                     }                     cnt[s[left]-'a']--;                     if(cnt[s[left]-'a']==0){ //窗口左界右移时,某一字符数出现次数等于0,那么少于k次的字符数减1,因为没有这个字符了                         less--;                         total--;                     }                     left++; // 窗口左界右移一位。                 }             }             if(lgst_left!=lgst_right&& lgst_right - lgst_left > res_right - res_left){  // 如果产生了出现次数都不少于K次的子字符,比较下该子字符串是否比较长,比较长就替换现有的。                 res_left = lgst_left;                 res_right = lgst_right;             }         }         if(res_right == res_left && k == 1 && s.size() == 1) return 1;   //单独情况,字符串只有一个字符,并且出现只有一次的情况         return res_right!=res_left ? res_right - res_left + 1:0;     } };

标签:子串,字符,right,窗口,res,395,滑动,lgst,left
From: https://www.cnblogs.com/daniel123/p/17004287.html

相关文章