每日一题:找出最长的超赞子字符串
题意
给你一个字符串 s 。请返回 s 中最长的 超赞子字符串 的长度。
「超赞子字符串」需满足满足下述两个条件:
该字符串是 s 的一个非空子字符串
进行任意次数的字符交换重新排序后,该字符串可以变成一个回文字符串
Solution
首先,一个字符串可以重新排序得到一个回文字符串的充要条件是:对字符计数,出现奇数次的字符个数小于等于1。
由此我们可以发现:我们没有必要知道这个数字到底出现了几次,我们只需要关心它到底是出现了奇数次还是偶数次。我们用 $0,1$ 来表示出现了 $偶数/奇数$ 次,由于需要统计的字符只有 $0-9$ 十个数字,因此我们只需要一个十位的二进制数 $status$ 即可表示当前所有字符出现次数的奇偶状态,即第i位表示数字 $i$ 出现次数的奇偶性。
假设当前遇到的数字是 i ,那么更新它的状态就是 $status ^= (1 << i)$ ,因为根据异或的特性,相同为0,不同为1,能够很好的实现我们需要的 $奇+奇(1+1)=偶+偶(0+0)=偶(0),奇+偶(1+0)= 偶+奇(0+1)=奇(1)$,改变对应二进制位的状态。
我们遍历字符串维护这样一个 $status$,采用数组标记的思想,$pre[status]$ 表示 $status$ 出现的最早位置。
满足超赞字符串的条件:
再一次遇到之前已经出现过的 $status$ ,说明所有数字都出现了偶数次。(因为每一位二进制位的奇偶性都相同的话,不论都是1还是0,$奇-奇=偶-偶=偶$,都代表这些字符在中间这一段出现了偶数次,长度为 $当前位置i - 最早出现的位置pre[status]$)
与之前出现过的 $status$ 只有一个二进制位不同,说明这个不同的二进制位出现了奇数次 $(奇-偶=偶-奇=奇)$,其余的二进制位出现了偶数次,仍然满足回文字符串的条件。针对这种情况,我们只需要从 $0-9$ 枚举二进制位,然后看之前是否出现过即可,同时维护答案。
Code
1 | class Solution { |