leetcode.1371 每个元音包含偶数次的最长子字符串

1371. 每个元音包含偶数次的最长子字符串

难度中等191收藏分享切换为英文关注反馈

给你一个字符串 s ,请你返回满足以下条件的最长子字符串的长度:每个元音字母,即 'a','e','i','o','u' ,在子字符串中都恰好出现了偶数次。

 

示例 1:

输入:s = "eleetminicoworoep"
输出:13
解释:最长子字符串是 "leetminicowor" ,它包含 e,i,o 各 2 个,以及 0 个 au 

示例 2:

输入:s = "leetcodeisgreat"
输出:5
解释:最长子字符串是 "leetc" ,其中包含 2 个 e

示例 3:

输入:s = "bcbcbc"
输出:6
解释:这个示例中,字符串 "bcbcbc" 本身就是最长的,因为所有的元音 a,e,i,o,u 都出现了 0 次。

 

提示:

  • 1 <= s.length <= 5 x 10^5
  • s 只包含小写英文字母。

以我的智商,只能想到遍历

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int findTheLongestSubstring(string s) {
	int i, j, k;
	int len = s.size();
	int maxlen = 0;
	int counta;
	int counte;
	int counti;
	int counto;
	int countu;
	int jj, ii, aa;
    for(i = 0; i < len; i++){
    	for(j = i; j < len; j++){
    		counta = 0;
    		counte = 0;
    		counti = 0;
    		counto = 0;
    		countu = 0;
    		for(k = i; k <= j; k++){
    			if(s[k] == 'a'){
    				counta++;
    			}
    			if(s[k] == 'e'){
    				counte++;
    			}    			
    			if(s[k] == 'i'){
    				counti++;
    			}
    			if(s[k] == 'o'){
    				counto++;
    			}
    			if(s[k] == 'u'){
    				countu++;
    			}   
 		    			
    		}
   			if((counta % 2 == 0) and (counte % 2 == 0) and (counti % 2 == 0) and (counto % 2 == 0) and (countu % 2 == 0)){
				if(j - i + 1 > maxlen){
					maxlen = j - i + 1;
					jj = j;
					ii = i;
					aa = counta;
				}
			} 	    		
    	}

    }
    cout << maxlen << endl;
    return maxlen;
}


int main(){
	string s = "id";
	findTheLongestSubstring(s);
	return 0;
}

果然不出我所料,超时了

借鉴了大佬,果然智慧,用到了哈希表和状态压缩

听着好像一脸懵,其实哈希表你就想是一个一对一的字典,找起来更快一些

而状态压缩就是换了一种判断的方式

#include <iostream>
#include <cstdio>
#include <cstring>
#include<unordered_map>

using namespace std;

int findTheLongestSubstring(string s) {
    // aeiou每个元音用一个bit一共5个bit,共有32种奇偶次数组合状态,比如10101可以表示aiu出现奇数次数
    // oe则出现偶数次数,每当遍历一个字符,就可以改变当前的aeiou出现的奇偶次数,也即是改变状态
    // 显然,如果两次出现了同样的状态,假设第一次出现在i处
    // 第二次出现在j处,那么i+1-j之间的字符串肯定是满足aeiou出现均为偶数次数的
    // 因为每一位只有经历偶数次变化才能变回原样
    // 为了使得合理的字符串最长
    // 那么第一次出现此状态时,就需要记录到下标,然后下次遇到相同状态,计算最大长度
    unordered_map<int, int> stateToIndex;
    int state = 0x0;
    // 初始化,刚开始时,state的状态已经是0x00000,已经出现,因此必须记录
    stateToIndex[state] = -1; 
    // a e i o u 分别在第12345个bit,来表示出现次数的奇偶性
    int maxlen = 0;
    for (int i = 0; i < s.size(); i++) {
        if (s[i] == 'a') state ^= 0x00001;
        if (s[i] == 'e') state ^= 0x00010;
        if (s[i] == 'i') state ^= 0x00100;
        if (s[i] == 'o') state ^= 0x01000;
        if (s[i] == 'u') state ^= 0x10000;
        if (stateToIndex.count(state)) maxlen = max(maxlen, i - stateToIndex[state]);
        else stateToIndex[state] = i;
    }
    cout << maxlen << endl;
    return maxlen;
}


int main(){
	string s = "id";
	findTheLongestSubstring(s);
	return 0;
}

解释我写在了代码中

希望对你有帮助

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章