LC每日一题|20240520 - 1542. 找出最长的超赞子字符串

159 阅读2分钟

LC每日一题|20240520 - 1542. 找出最长的超赞子字符串

给你一个字符串 s 。请返回 s 中最长的 超赞子字符串 的长度。

「超赞子字符串」需满足满足下述两个条件:

  • 该字符串是 s 的一个非空子字符串
  • 进行任意次数的字符交换后,该字符串可以变成一个回文字符串

提示:

  • 1 <= s.length <= 10^5
  • s 仅由数字组成

题目难度:Hard

解题思路

非常简单的一道状压~

我们知道,欲使某个字符串在不定次交换之后变成回文串,该串需满足至多一个元素出现奇数次的条件。

那么我们可以统计一下遍历到某一下标时每个数字出现次数的奇偶,将其维护为一个10bit的状态。此时,对两个不同的下标观察其状态,如果第i位相同,则说明在该区间中数字i出现了偶数次,反之就是出现了奇数次。我们可以记录每个状态第一次出现时的下标,同时通过异或构建与当前状态的二进制只差1位的新状态,遍历中维护当前下标减去对应所有合法的目标状态第一次出现的下标的最大值。

AC代码

class Solution {
    fun longestAwesome(s: String): Int {
        val c = Array(s.length + 1) { IntArray(10) }
        val min = IntArray(1024) { -1 }
        min[0] = 0
        var res = 0
        for (i in 1 .. s.length) {
            var t = 0
            for (j in 0 .. 9) {
                c[i][j] = c[i - 1][j]
                if (s[i - 1] - '0' == j) c[i][j]++
                c[i][j] %= 2
                t *= 2
                t += c[i][j]
            }
            if (min[t] == -1) min[t] = i
            res = Math.max(res, i - min[t])
            for (j in 0..9) {
                val x = t xor (1 shl j)
                if (min[x] != -1) res = Math.max(res, i - min[x])
            } 
        }
        return res
    }
}
}