
题目描述
给你一个下标从 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
只包含小写英文字母。
解法
方法一
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 | class Solution:
def maxProduct(self, s: str) -> int:
n = len(s)
hlen = [0] * n
center = right = 0
for i in range(n):
if i < right:
hlen[i] = min(right - i, hlen[2 * center - i])
while (
0 <= i - 1 - hlen[i]
and i + 1 + hlen[i] < len(s)
and s[i - 1 - hlen[i]] == s[i + 1 + hlen[i]]
):
hlen[i] += 1
if right < i + hlen[i]:
center, right = i, i + hlen[i]
prefix = [0] * n
suffix = [0] * n
for i in range(n):
prefix[i + hlen[i]] = max(prefix[i + hlen[i]], 2 * hlen[i] + 1)
suffix[i - hlen[i]] = max(suffix[i - hlen[i]], 2 * hlen[i] + 1)
for i in range(1, n):
prefix[~i] = max(prefix[~i], prefix[~i + 1] - 2)
suffix[i] = max(suffix[i], suffix[i - 1] - 2)
for i in range(1, n):
prefix[i] = max(prefix[i - 1], prefix[i])
suffix[~i] = max(suffix[~i], suffix[~i + 1])
return max(prefix[i - 1] * suffix[i] for i in range(1, n))
|
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
53 | class Solution {
public long maxProduct(String s) {
int n = s.length();
if (n == 2) return 1;
int[] len = manachers(s);
long[] left = new long[n];
int max = 1;
left[0] = max;
for (int i = 1; i <= n - 1; i++) {
if (len[(i - max - 1 + i) / 2] > max) max += 2;
left[i] = max;
}
max = 1;
long[] right = new long[n];
right[n - 1] = max;
for (int i = n - 2; i >= 0; i--) {
if (len[(i + max + 1 + i) / 2] > max) max += 2;
right[i] = max;
}
long res = 1;
for (int i = 1; i < n; i++) {
res = Math.max(res, left[i - 1] * right[i]);
}
return res;
}
private int[] manachers(String s) {
int len = s.length();
int[] P = new int[len];
int c = 0;
int r = 0;
for (int i = 0; i < len; i++) {
int mirror = (2 * c) - i;
if (i < r) {
P[i] = Math.min(r - i, P[mirror]);
}
int a = i + (1 + P[i]);
int b = i - (1 + P[i]);
while (a < len && b >= 0 && s.charAt(a) == s.charAt(b)) {
P[i]++;
a++;
b--;
}
if (i + P[i] > r) {
c = i;
r = i + P[i];
}
}
for (int i = 0; i < len; i++) {
P[i] = 1 + 2 * P[i];
}
return P;
}
}
|
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 | class Solution {
public:
long long maxProduct(string s) {
long long res = 0, l = 0, n = s.size();
vector<int> m(n), r(n);
for (int i = 0, l = 0, r = -1; i < n; ++i) {
int k = (i > r) ? 1 : min(m[l + r - i], r - i + 1);
while (0 <= i - k && i + k < n && s[i - k] == s[i + k])
k++;
m[i] = k--;
if (i + k > r) {
l = i - k;
r = i + k;
}
}
queue<array<int, 2>> q, q1;
for (int i = n - 1; i >= 0; --i) {
while (!q.empty() && q.front()[0] - q.front()[1] > i - 1)
q.pop();
r[i] = 1 + (q.empty() ? 0 : (q.front()[0] - i) * 2);
q.push({i, m[i]});
}
for (int i = 0; i < n - 1; i++) {
while (!q1.empty() && q1.front()[0] + q1.front()[1] < i + 1)
q1.pop();
l = max(l, 1ll + (q1.empty() ? 0 : (i - q1.front()[0]) * 2));
res = max(res, l * r[i + 1]);
q1.push({i, m[i]});
}
return res;
}
};
|
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
53
54
55
56
57 | func maxProduct(s string) int64 {
n := len(s)
hlen := make([]int, n)
center, right := 0, 0
for i := 0; i < n; i++ {
if i < right {
mirror := 2*center - i
if mirror >= 0 && mirror < n {
hlen[i] = min(right-i, hlen[mirror])
}
}
for i-1-hlen[i] >= 0 && i+1+hlen[i] < n && s[i-1-hlen[i]] == s[i+1+hlen[i]] {
hlen[i]++
}
if i+hlen[i] > right {
center = i
right = i + hlen[i]
}
}
prefix := make([]int, n)
suffix := make([]int, n)
for i := 0; i < n; i++ {
r := i + hlen[i]
if r < n {
prefix[r] = max(prefix[r], 2*hlen[i]+1)
}
l := i - hlen[i]
if l >= 0 {
suffix[l] = max(suffix[l], 2*hlen[i]+1)
}
}
for i := 1; i < n; i++ {
if n-i-1 >= 0 {
prefix[n-i-1] = max(prefix[n-i-1], prefix[n-i]-2)
}
suffix[i] = max(suffix[i], suffix[i-1]-2)
}
for i := 1; i < n; i++ {
prefix[i] = max(prefix[i-1], prefix[i])
suffix[n-i-1] = max(suffix[n-i], suffix[n-i-1])
}
var res int64
for i := 1; i < n; i++ {
prod := int64(prefix[i-1]) * int64(suffix[i])
if prod > res {
res = prod
}
}
return res
}
|