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