3144. 分割字符频率相等的最少子字符串

发布于 2024-08-28  11 次阅读


给你一个字符串 s ,你需要将它分割成一个或者更多的 平衡 子字符串。比方说,s == "ababcc" 那么 ("abab", "c", "c") ,("ab", "abc", "c") 和 ("ababcc") 都是合法分割,但是 ("a", "bab", "cc") ,("aba", "bc", "c") 和 ("ab", "abcc") 不是,不平衡的子字符串用粗体表示。

请你返回 s 最少 能分割成多少个平衡子字符串。

注意:一个 平衡 字符串指的是字符串中所有字符出现的次数都相同。

示例 1:

输入:s = "fabccddg"

输出:3

解释:

我们可以将 s 分割成 3 个子字符串:("fab, "ccdd", "g") 或者 ("fabc", "cd", "dg") 。

示例 2:

输入:s = "abababaccddb"

输出:2

解释:

我们可以将 s 分割成 2 个子字符串:("abab", "abaccddb") 。

class Solution {
    public int minimumSubstringsInPartition(String S) {
        char[] s = S.toCharArray();
        int n = s.length;
        int[] memo = new int[n];
        return dfs(n - 1, s, memo);
    }

    private int dfs(int i, char[] s, int[] memo) {
        if (i < 0) {
            return 0;
        }
        if (memo[i] > 0) { // 之前计算过
            return memo[i];
        }
        int res = Integer.MAX_VALUE;
        int[] cnt = new int[26];
        int k = 0, maxCnt = 0;
        for (int j = i; j >= 0; j--) {
            k += cnt[s[j] - 'a']++ == 0 ? 1 : 0;
            maxCnt = Math.max(maxCnt, cnt[s[j] - 'a']);
            if (i - j + 1 == k * maxCnt) {
                res = Math.min(res, dfs(j - 1, s, memo) + 1);
            }
        }
        memo[i] = res; // 记忆化
        return res;
    }
}