Skip to content

Commit 264b187

Browse files
committed
feat: add solutions to lc problem: No.1147
1 parent c43e1f4 commit 264b187

File tree

7 files changed

+637
-58
lines changed

7 files changed

+637
-58
lines changed

solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/README.md

Lines changed: 287 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,26 @@
5555

5656
<!-- 这里可写通用的实现逻辑 -->
5757

58-
**方法一:贪心 + 递归**
58+
**方法一:贪心 + 递归或双指针**
5959

60-
从字符串的两端开始,如果两端的字符相同,则可以贪心地将这两端的字符作为一段回文串,然后递归处理中间的字符串。
60+
我们可以从字符串的两端开始,寻找长度最短的、相同且不重叠的前后缀:
6161

62-
时间复杂度 $O(n^2)$,其中 $n$ 为字符串的长度。
62+
- 如果找不到这样的前后缀,那么整个字符串作为一个段式回文,答案加 $1$;
63+
- 如果找到了这样的前后缀,那么这个前后缀作为一个段式回文,答案加 $2$,然后继续寻找剩下的字符串的前后缀。这里我们可以使用递归或双指针来实现。
64+
65+
以上贪心策略的证明如下:
66+
67+
假设有一个前后缀 $A_1$ 和 $A_2$ 满足条件,又有一个前后缀 $B_1$ 和 $B_4$ 满足条件,由于 $A_1 = A_2$,且 $B_1=B_4$,那么有 $B_3=B_1=B_4=B_2$,并且 $C_1 = C_2$,因此,如果我们贪心地将 $B_1$ 和 $B_4$ 分割出来,那么剩下的 $C_1$ 和 $C_2$,以及 $B_2$ 和 $B_3$ 也能成功分割。因此我们应该贪心地选择长度最短的相同前后缀进行分割,这样剩余的字符串中,将可能分割出更多的段式回文串。
68+
69+
<p><img alt="" src="https://fastly.jsdelivr.net/gh/doocs/leetcode@main/solution/1100-1199/1147.Longest%20Chunked%20Palindrome%20Decomposition/images/demo.png" style="width: 300px;" /></p>
70+
71+
时间复杂度 $O(n^2)$,空间复杂度 $O(n)$ 或 $O(1)$。其中 $n$ 为字符串的长度。
72+
73+
**方法二:字符串哈希**
74+
75+
在方法一的基础上,我们可以使用字符串哈希的方法,在 $O(1)$ 时间内比较两个字符串是否相等。
76+
77+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串的长度。
6378

6479
<!-- tabs:start -->
6580

@@ -75,10 +90,68 @@ class Solution:
7590
return n
7691
for i in range(n // 2 + 1):
7792
if text[:i] == text[-i:]:
78-
return 2 + self.longestDecomposition(text[i: -i])
93+
return 2 + self.longestDecomposition(text[i:-i])
7994
return 1
8095
```
8196

97+
```python
98+
class Solution:
99+
def longestDecomposition(self, text: str) -> int:
100+
ans = 0
101+
i, j = 0, len(text) - 1
102+
while i <= j:
103+
k = 1
104+
ok = False
105+
while i + k - 1 < j - k + 1:
106+
if text[i: i + k] == text[j - k + 1: j + 1]:
107+
ans += 2
108+
i += k
109+
j -= k
110+
ok = True
111+
break
112+
k += 1
113+
if not ok:
114+
ans += 1
115+
break
116+
return ans
117+
```
118+
119+
```python
120+
class Solution:
121+
def longestDecomposition(self, text: str) -> int:
122+
def get(l, r):
123+
return (h[r] - h[l - 1] * p[r - l + 1]) % mod
124+
125+
n = len(text)
126+
base = 131
127+
mod = int(1e9) + 7
128+
h = [0] * (n + 10)
129+
p = [1] * (n + 10)
130+
for i, c in enumerate(text):
131+
t = ord(c) - ord('a') + 1
132+
h[i + 1] = (h[i] * base) % mod + t
133+
p[i + 1] = (p[i] * base) % mod
134+
135+
136+
ans = 0
137+
i, j = 0, n - 1
138+
while i <= j:
139+
k = 1
140+
ok = False
141+
while i + k - 1 < j - k + 1:
142+
if get(i + 1, i + k) == get(j - k + 2, j + 1):
143+
ans += 2
144+
i += k
145+
j -= k
146+
ok = True
147+
break
148+
k += 1
149+
if not ok:
150+
ans += 1
151+
break
152+
return ans
153+
```
154+
82155
### **Java**
83156

84157
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -103,30 +176,29 @@ class Solution {
103176
```java
104177
class Solution {
105178
public int longestDecomposition(String text) {
106-
char[] cs = text.toCharArray();
107-
int res = 0;
108-
for (int i = 0, j = cs.length - 1; i <= j;) {
109-
boolean flag = true;
179+
int ans = 0;
180+
for (int i = 0, j = text.length() - 1; i <= j;) {
181+
boolean ok = false;
110182
for (int k = 1; i + k - 1 < j - k + 1; ++k) {
111-
if (check(cs, i, j - k + 1, k)) {
112-
res += 2;
183+
if (check(text, i, j - k + 1, k)) {
184+
ans += 2;
113185
i += k;
114186
j -= k;
115-
flag = false;
187+
ok = true;
116188
break;
117189
}
118190
}
119-
if (flag) {
120-
++res;
191+
if (!ok) {
192+
++ans;
121193
break;
122194
}
123195
}
124-
return res;
196+
return ans;
125197
}
126198

127-
private boolean check(char[] cs, int i, int j, int k) {
199+
private boolean check(String s, int i, int j, int k) {
128200
while (k-- > 0) {
129-
if (cs[i++] != cs[j++]) {
201+
if (s.charAt(i++) != s.charAt(j++)) {
130202
return false;
131203
}
132204
}
@@ -135,6 +207,48 @@ class Solution {
135207
}
136208
```
137209

210+
```java
211+
class Solution {
212+
private long[] h;
213+
private long[] p;
214+
215+
public int longestDecomposition(String text) {
216+
int n = text.length();
217+
int base = 131;
218+
h = new long[n + 10];
219+
p = new long[n + 10];
220+
p[0] = 1;
221+
for (int i = 0; i < n; ++i) {
222+
int t = text.charAt(i) - 'a' + 1;
223+
h[i + 1] = h[i] * base + t;
224+
p[i + 1] = p[i] * base;
225+
}
226+
int ans = 0;
227+
for (int i = 0, j = n - 1; i <= j;) {
228+
boolean ok = false;
229+
for (int k = 1; i + k - 1 < j - k + 1; ++k) {
230+
if (get(i + 1, i + k) == get(j - k + 2, j + 1)) {
231+
ans += 2;
232+
i += k;
233+
j -= k;
234+
ok = true;
235+
break;
236+
}
237+
}
238+
if (!ok) {
239+
++ans;
240+
break;
241+
}
242+
}
243+
return ans;
244+
}
245+
246+
private long get(int i, int j) {
247+
return h[j] - h[i - 1] * p[j - i + 1];
248+
}
249+
}
250+
```
251+
138252
### **C++**
139253

140254
```cpp
@@ -153,6 +267,82 @@ public:
153267
};
154268
```
155269
270+
```cpp
271+
class Solution {
272+
public:
273+
int longestDecomposition(string text) {
274+
int ans = 0;
275+
auto check = [&](int i, int j, int k) -> bool {
276+
while (k--) {
277+
if (text[i++] != text[j++]) {
278+
return false;
279+
}
280+
}
281+
return true;
282+
};
283+
for (int i = 0, j = text.size() - 1; i <= j;) {
284+
bool ok = false;
285+
for (int k = 1; i + k - 1 < j - k + 1; ++k) {
286+
if (check(i, j - k + 1, k)) {
287+
ans += 2;
288+
i += k;
289+
j -= k;
290+
ok = true;
291+
break;
292+
}
293+
}
294+
if (!ok) {
295+
ans += 1;
296+
break;
297+
}
298+
}
299+
return ans;
300+
}
301+
};
302+
```
303+
304+
```cpp
305+
class Solution {
306+
public:
307+
int longestDecomposition(string text) {
308+
using ull = unsigned long long;
309+
int n = text.size();
310+
int base = 131;
311+
ull p[n + 10];
312+
ull h[n + 10];
313+
p[0] = 1;
314+
h[0] = 0;
315+
for (int i = 0; i < n; ++i) {
316+
int t = text[i] - 'a' + 1;
317+
p[i + 1] = p[i] * base;
318+
h[i + 1] = h[i] * base + t;
319+
}
320+
321+
int ans = 0;
322+
auto get = [&](int l, int r) {
323+
return h[r] - h[l - 1] * p[r - l + 1];
324+
};
325+
for (int i = 0, j = n - 1; i <= j;) {
326+
bool ok = false;
327+
for (int k = 1; i + k - 1 < j - k + 1; ++k) {
328+
if (get(i + 1, i + k) == get(j - k + 2, j + 1)) {
329+
ans += 2;
330+
i += k;
331+
j -= k;
332+
ok = true;
333+
break;
334+
}
335+
}
336+
if (!ok) {
337+
++ans;
338+
break;
339+
}
340+
}
341+
return ans;
342+
}
343+
};
344+
```
345+
156346
### **Go**
157347

158348
```go
@@ -170,6 +360,64 @@ func longestDecomposition(text string) int {
170360
}
171361
```
172362

363+
```go
364+
func longestDecomposition(text string) (ans int) {
365+
for i, j := 0, len(text)-1; i <= j; {
366+
ok := false
367+
for k := 1; i+k-1 < j-k+1; k++ {
368+
if text[i:i+k] == text[j-k+1:j+1] {
369+
ans += 2
370+
i += k
371+
j -= k
372+
ok = true
373+
break
374+
}
375+
}
376+
if !ok {
377+
ans++
378+
break
379+
}
380+
}
381+
return
382+
}
383+
```
384+
385+
```go
386+
func longestDecomposition(text string) (ans int) {
387+
n := len(text)
388+
base := 131
389+
h := make([]int, n+10)
390+
p := make([]int, n+10)
391+
p[0] = 1
392+
for i, c := range text {
393+
t := int(c-'a') + 1
394+
p[i+1] = p[i] * base
395+
h[i+1] = h[i]*base + t
396+
}
397+
get := func(l, r int) int {
398+
return h[r] - h[l-1]*p[r-l+1]
399+
}
400+
401+
for i, j := 0, n-1; i <= j; {
402+
ok := false
403+
for k := 1; i+k-1 < j-k+1; k++ {
404+
if get(i+1, i+k) == get(j-k+2, j+1) {
405+
ans += 2
406+
i += k
407+
j -= k
408+
ok = true
409+
break
410+
}
411+
}
412+
if !ok {
413+
ans++
414+
break
415+
}
416+
}
417+
return
418+
}
419+
```
420+
173421
### **TypeScript**
174422

175423
```ts
@@ -187,6 +435,29 @@ function longestDecomposition(text: string): number {
187435
}
188436
```
189437

438+
```ts
439+
function longestDecomposition(text: string): number {
440+
let ans = 0;
441+
for (let i = 0, j = text.length - 1; i <= j; ) {
442+
let ok = false;
443+
for (let k = 1; i + k - 1 < j - k + 1; ++k) {
444+
if (text.slice(i, i + k) === text.slice(j - k + 1, j + 1)) {
445+
ans += 2;
446+
i += k;
447+
j -= k;
448+
ok = true;
449+
break;
450+
}
451+
}
452+
if (!ok) {
453+
++ans;
454+
break;
455+
}
456+
}
457+
return ans;
458+
}
459+
```
460+
190461
### **...**
191462

192463
```

0 commit comments

Comments
 (0)