1960. 两个回文子字符串长度的最大乘积Java
文章发布较早,内容可能过时,阅读注意甄别。
# 题目
给你一个下标从 0 开始的字符串 s ,你需要找到两个 不重叠的回文 子字符串,它们的长度都必须为 奇数 ,使得它们长度的乘积最大。
更正式地,你想要选择四个整数 i ,j ,k ,l ,使得 0 <= i <= j < k <= l < s.length ,且子字符串 s[i...j] 和 s[k...l] 都是回文串且长度为奇数。s[i...j] 表示下标从 i 到 j 且 包含 两端下标的子字符串。
请你返回两个不重叠回文子字符串长度的 最大 乘积。
回文字符串 指的是一个从前往后读和从后往前读一模一样的字符串。子字符串 指的是一个字符串中一段连续字符。
示例 1:
输入:s = "ababbb"
输出:9
解释:子字符串 "aba" 和 "bbb" 为奇数长度的回文串。乘积为 3 * 3 = 9 。
示例 2:
输入:s = "zaaaxbbby"
输出:9
解释:子字符串 "aaa" 和 "bbb" 为奇数长度的回文串。乘积为 3 * 3 = 9 。
提示:
- 2 <= s.length <= 105
- s 只包含小写英文字母。
# 思路
马拉车+前缀后缀和
# 解法
class Solution {
public long maxProduct(String s) {
String changed = process(s);
int n = changed.length();
int[] p = new int[n];
int center = 0, mx = 0;
for (int i = 1; i < n - 1; i++) {
if (i < mx) {
p[i] = Math.min(mx - i, p[center * 2 - i]);
} else {
p[i] = 0;
}
while (changed.charAt(i + p[i] + 1) == changed.charAt(i - p[i] - 1)) {
p[i]++;
}
if (i + p[i] > mx) {
mx = i + p[i];
center = i;
}
}
long[] leftDP = new long[n];
long[] rightDP = new long[n];
for (int i = 1; i < n; i++) {
leftDP[i + p[i]] = Math.max(leftDP[i + p[i]], p[i] * 2 + 1);
rightDP[i - p[i]] = Math.max(rightDP[i - p[i]], p[i] * 2 + 1);
}
for (int i = n - 2; i >= 1; i--) {
leftDP[i] = Math.max(leftDP[i], leftDP[i + 1] - 2);
}
for (int i = 1; i <= n - 2; i++) {
rightDP[i] = Math.max(rightDP[i], rightDP[i - 1] - 2);
}
for (int i = 1; i <= n - 2; i++) {
leftDP[i] = Math.max(leftDP[i], leftDP[i - 1]);
}
for (int i = n - 2; i >= 1; i--) {
rightDP[i] = Math.max(rightDP[i], rightDP[i + 1]);
}
long ans = 0;
for (int i = 1; i < n - 2; i++) {
ans = Math.max(ans, leftDP[i] * rightDP[i + 1]);
}
return ans;
}
public String process(String s) {
StringBuilder ans = new StringBuilder("^");
ans.append(s);
ans.append("$");
return ans.toString();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# 总结
- 分析出几种情况,然后分别对各个情况实现