leetcode刷题-1371-每个元音包含偶数次的最长字符串

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

给你一个字符串 s ,请你返回满足以下条件的最长子字符串的长度:每个元音字母,即 ‘a’,‘e’,‘i’,‘o’,‘u’ ,在子字符串中都恰好出现了偶数次。
示例1:
s = “eleetminicoworep”
输出: 13

思路
1)遍历所有子字符串;超时
2)每一个字符串就是一个区间,区间状态可以用前缀和,用pre[i][k]记录第i个字符串之前第k个元音的个数,[j,i] 字符串的某个元音的个数就是pre[i][k]-pre[j-1][k]。判断每个元音是否符合,还是需要遍历两次。
3)奇偶性。题目中偶数次,所以我们不必在意出现多少次,只需要在意出现为奇数次或者偶数次,因为偶数-偶数=偶数,奇数-奇数=偶数。所以我们只需要记录每个元音的在第i个字符的状态,0=偶数,1=奇数,键值对应多用Hash存储。键为元音字母,值为奇偶性。但是一旦键变多,不好维护。

可以采用bitmap来存储。二进制每一位正好对应奇偶性两种状态,因为有五位,最大为11111=2^5-1,所以用一个32大小数组的数据存储对应状态的下标。
如 :s=“aba”;start = 00000;
s[0] = a = 00001,00000^00001 = 00001;a出现奇数次;
s[1] = b = 00010,00001^00010 = 00011;a,b出现奇数次;
s[2] = a = 00001,00011^00001 = 00010; a出现偶数次,b出现奇数次。
代码:

class Sulation{
	int findTheLongestSubstring(string s){
		//status状态
		int ans = 0,status = 0,n = s.size();
		//前置位未开始遍历数组为0
		pos[0] = 0;
		//遍历字符串,更新状态
		for(int i = 0;i < n;++i){
			if(s[i] == 'a') status ^= 1<<0; 
			else if(s[i] == 'e') status ^=1<<1;
			else if(s[i] == 'i') status ^=1<<2;
			else if(s[i] == 'o') status ^=1<<3;
			else if(s[i] == 'u') status ^=1<<4;
			//如果这种相同的状态出现,说明符合要求,计算子字符串长度,
			if(pos[status]!=-1)
				ans = max(ans,i+1-pos[status]);
				//如果状态之前没出现过,计算位置坐标加1
			else
				pos[status] = i+1;
		}
		return ans;
	}
}

PS:个人理解:针对pos[0] =0,和ans = max(ans,i+1-pos[status])\pos[status] = i+1;
如图:
位置 0 1 2 3 4 5
字符串 a b a b a
下标 0 1 2 3 4
数组pos[]记录的是元音字母第一次出现的位置,pos[0] = 0没有开始遍历。i+1使得下标对应上位置
Python:
下标即位置,规定dp[0]=1;

def findTheLongestString(self,s:str)->int:
	dp = [-float('inf')]*32
	dp[0] = -1
	pattern = 0
	ans = 0
	for i in rang(len(s)):
		if s[i] =='a':
			pattern^=(1<<0)
		elif s[i] == 'e':
			pattern^=(1<<1)
		elif s[i] == 'i':
			pattern^=(1<<2)
		elif s[i] == 'o':
			pattern^=(1<<3)
		elif s[i] == 'u':
			pattern^=(1<<4)
		if dp[pattern] != -float('inf'):
			cur_len = i-dp[pattern]
			res = max(cur_len,res)
		else:
			dp[pattern] = i 
	return res

参考链接:https://leetcode-cn.com/problems/find-the-longest-substring-containing-vowels-in-even-counts/solution/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值