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

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

难度:中等
2020/5/20每日一题打卡 √ 前缀和+状态压缩+哈希表
今天2020520,算是一个很特别的日子了!
但是每日一题还是要写的(抄题解的一天)
类似的题:1124. 表现良好的最长时间段
题目描述
在这里插入图片描述
解题思路
参考题解:每个元音包含偶数次的最长子字符串 官方题解
❤将题目一步步等价转化 | “非奇即偶” 与二进制的联系
模模糊糊的看懂了一点
首先由 最长连续子串这点想到前缀和,前缀和能效率很高的遍历区间找到符合要求的,比如优美子数组的那道题。然后为了方便的判断两个区间是否满足要求,对状态进行压缩,用5位二进制位来表示每个元音的奇偶性。每出现一个元音字母,就用上一个状态和对应的位进行异或,利用了异或的特性,异或一次是1,两次就是0.
依次求出每个位置的状态,找一找前面有没有相同的状态,如果有就采用最左边那个计算距离,然后找最大的距离。
为什么相同的状态是满足要求的呢,比如一开始的时候是00000,每个元音都没出现过,遍历到某个位置满足要求,每个元音都出现了偶数次,这时状态还是00000,把当前下标和上一个下标相减就得到了区间长度
因为这里状态有限而且能算出来,所以可以用数组来代替哈希表会更高效,用哈希表也可以的

 /*
	  * 1371. 每个元音包含偶数次的最长子字符串
	  * 2020//5/20每日一题打卡  状态压缩+前缀+哈希表
	  */
	 public int findTheLongestSubstring(String s) {
		 int n = s.length();
		 int[] pos = new int[1 << 5];  //位运算,左移 = 1*2^5 用五位二进制位来表示aeiou 存储对应状态出现的最早位置
		 Arrays.fill(pos, -1);   //初始化,没记录就是-1
	     int re = 0, status = 0;
	     pos[0] = 0;
		 for (int i = 0; i < n; i++) {
			char c = s.charAt(i);
			switch (c) {
			case 'a':
				status ^= (1<<0);    //异或,同0异1
				break;
			case 'e':
				status ^= (1<<1);    
				break;
			case 'i':
				status ^= (1<<2);    
				break;
			case 'o':
				status ^= (1<<3);    
				break;
			case 'u':
				status ^= (1<<4);    
				break;
			default:
				break;
			}
			if(pos[status] >= 0) {  //大于等于0说明之前出现过这个状态,维护最大值
				re = Math.max(re, i-pos[status]+1);
			}else {
				pos[status] = i + 1;
			}
		}

		 return re;
	    }

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值