55
55
56
56
<!-- 这里可写通用的实现逻辑 -->
57
57
58
- ** 方法一:贪心 + 递归 **
58
+ ** 方法一:贪心 + 递归或双指针 **
59
59
60
- 从字符串的两端开始,如果两端的字符相同,则可以贪心地将这两端的字符作为一段回文串,然后递归处理中间的字符串。
60
+ 我们可以从字符串的两端开始,寻找长度最短的、相同且不重叠的前后缀:
61
61
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$ 为字符串的长度。
63
78
64
79
<!-- tabs:start -->
65
80
@@ -75,10 +90,68 @@ class Solution:
75
90
return n
76
91
for i in range (n // 2 + 1 ):
77
92
if text[:i] == text[- i:]:
78
- return 2 + self .longestDecomposition(text[i: - i])
93
+ return 2 + self .longestDecomposition(text[i:- i])
79
94
return 1
80
95
```
81
96
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
+
82
155
### ** Java**
83
156
84
157
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -103,30 +176,29 @@ class Solution {
103
176
``` java
104
177
class Solution {
105
178
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 ;
110
182
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 ;
113
185
i += k;
114
186
j -= k;
115
- flag = false ;
187
+ ok = true ;
116
188
break ;
117
189
}
118
190
}
119
- if (flag ) {
120
- ++ res ;
191
+ if (! ok ) {
192
+ ++ ans ;
121
193
break ;
122
194
}
123
195
}
124
- return res ;
196
+ return ans ;
125
197
}
126
198
127
- private boolean check (char [] cs , int i , int j , int k ) {
199
+ private boolean check (String s , int i , int j , int k ) {
128
200
while (k-- > 0 ) {
129
- if (cs[ i++ ] != cs[ j++ ] ) {
201
+ if (s . charAt( i++ ) != s . charAt( j++ ) ) {
130
202
return false ;
131
203
}
132
204
}
@@ -135,6 +207,48 @@ class Solution {
135
207
}
136
208
```
137
209
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
+
138
252
### ** C++**
139
253
140
254
``` cpp
@@ -153,6 +267,82 @@ public:
153
267
};
154
268
```
155
269
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
+
156
346
### ** Go**
157
347
158
348
``` go
@@ -170,6 +360,64 @@ func longestDecomposition(text string) int {
170
360
}
171
361
```
172
362
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
+
173
421
### ** TypeScript**
174
422
175
423
``` ts
@@ -187,6 +435,29 @@ function longestDecomposition(text: string): number {
187
435
}
188
436
```
189
437
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
+
190
461
### ** ...**
191
462
192
463
```
0 commit comments