【LeetCode 每日一题】1147. 段式回文

87 阅读1分钟

1147. 段式回文

难度:困难

时间:2023/04/12


你会得到一个字符串 text 。你应该把它分成 k 个子字符串 (subtext1, subtext2,…, subtextk) ,要求满足:

  • subtexti 是 非空  字符串
  • 所有子字符串的连接等于 text ( 即subtext1 + subtext2 + ... + subtextk == text )
  • 对于所有 i 的有效值( 即 1 <= i <= k ) ,subtexti == subtextk - i + 1 均成立

返回k可能最大值。

示例 1:

输入:text = "ghiabcdefhelloadamhelloabcdefghi"
输出:7
解释:我们可以把字符串拆分成 "(ghi)(abcdef)(hello)(adam)(hello)(abcdef)(ghi)"。

示例 2:

输入:text = "merchant"
输出:1
解释:我们可以把字符串拆分成 "(merchant)"

示例 3:

输入:text = "antaprezatepzapreanta"
输出:11
解释:我们可以把字符串拆分成 "(a)(nt)(a)(pre)(za)(tpe)(za)(pre)(a)(nt)(a)"。

提示:

  • 1 <= text.length <= 1000
  • text 仅由小写英文字符组成

解题思路:

方法1:字符串哈希

  • 快速判断两个串是否相等,判断一个字符串是否出现过,字符串哈希实质上就是把每个不同的字符串转成不同的整数。 可以发现,与一个string有关的HASH值不仅仅跟每个字符的个数有关,还和字符所在的位数有关。
  • 在本题中只需要计算左端pre和右端suf的字符串哈希是否一样,如果一样的话,说明左端和右端可以构成段式回文。
  • base = 131
  • 因为在构造哈希函数会出现冲突,所以在选择进制时尽量选择131,13331等质数,冲突的可能性更小。
using ull = unsigned long long;
class Solution {
public:
    int longestDecomposition(string t) {
        int n = t.size(), base = 131;
        ull pre = 0, suf = 0, mul = 1;
        int ans = 0;
        for (int i = 0, j = n - 1; i < j; i += 1, j -= 1) {
            pre = (pre * base + t[i] - 'a');
            suf = ((t[j] - 'a') * mul + suf);
            mul = mul * base;
            if (pre == suf) {
                ans += 2;
                pre = suf = 0;
                mul = 1;
                if (i == j - 1) return ans;
            }
        }
        return ans + 1;
    }
};

方法2:贪心

  • 贪心解法的思路是找到最短的相等前后缀,将字符串拆分为前缀,中间字符串,后缀。
  • 答案为2 + 中间字符串的回文段数
class Solution:
    def longestDecomposition(self, s: str) -> int:
        ans = 0
        while s:
            i = 1
            while i <= len(s) // 2 and s[:i] != s[-i:]:
                i += 1
            if i > len(s) // 2:
                ans += 1
                break
            ans += 2
            s = s[i:-i]
        return ans