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;
}

解釋我寫在了代碼中

希望對你有幫助

 

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