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 <= 1000text仅由小写英文字符组成
解题思路:
方法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