Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9f31a94

Browse files
authoredAug 15, 2024
feat: add solutions to lc problem: No.0214 (doocs#3416)
No.0214.Shortest Palindrome
1 parent a7c9dd4 commit 9f31a94

File tree

9 files changed

+506
-100
lines changed

9 files changed

+506
-100
lines changed
 

‎solution/0200-0299/0214.Shortest Palindrome/README.md

Lines changed: 183 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -201,43 +201,193 @@ impl Solution {
201201
#### C#
202202

203203
```cs
204-
// https://leetcode.com/problems/shortest-palindrome/
205-
206-
using System.Text;
207-
208-
public partial class Solution
209-
{
210-
public string ShortestPalindrome(string s)
211-
{
212-
for (var i = s.Length - 1; i >= 0; --i)
213-
{
214-
var k = i;
215-
var j = 0;
216-
while (j < k)
217-
{
218-
if (s[j] == s[k])
219-
{
220-
++j;
221-
--k;
222-
}
223-
else
224-
{
225-
break;
226-
}
204+
public class Solution {
205+
public string ShortestPalindrome(string s) {
206+
int baseValue = 131;
207+
int mul = 1;
208+
int mod = (int)1e9 + 7;
209+
int prefix = 0, suffix = 0;
210+
int idx = 0;
211+
int n = s.Length;
212+
213+
for (int i = 0; i < n; ++i) {
214+
int t = s[i] - 'a' + 1;
215+
prefix = (int)(((long)prefix * baseValue + t) % mod);
216+
suffix = (int)((suffix + (long)t * mul) % mod);
217+
mul = (int)(((long)mul * baseValue) % mod);
218+
if (prefix == suffix) {
219+
idx = i + 1;
227220
}
228-
if (j >= k)
229-
{
230-
var sb = new StringBuilder(s.Length * 2 - i - 1);
231-
for (var l = s.Length - 1; l >= i + 1; --l)
232-
{
233-
sb.Append(s[l]);
234-
}
235-
sb.Append(s);
236-
return sb.ToString();
221+
}
222+
223+
if (idx == n) {
224+
return s;
225+
}
226+
227+
return new string(s.Substring(idx).Reverse().ToArray()) + s;
228+
}
229+
}
230+
```
231+
232+
<!-- tabs:end -->
233+
234+
<!-- solution:end -->
235+
236+
<!-- solution:start -->
237+
238+
### 方法二:KMP 算法
239+
240+
根据题目描述,我们需要将字符串 $s$ 反转,得到字符串 $\textit{rev}$,然后求出字符串 $rev$ 的后缀与字符串 $s$ 的前缀的最长公共部分。我们可以使用 KMP 算法,将字符串 $s$ 与字符串 $rev$ 连接起来,求出其最长前缀与最长后缀的最长公共部分。
241+
242+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $s$ 的长度。
243+
244+
<!-- tabs:start -->
245+
246+
#### Python3
247+
248+
```python
249+
class Solution:
250+
def shortestPalindrome(self, s: str) -> str:
251+
t = s + "#" + s[::-1] + "$"
252+
n = len(t)
253+
next = [0] * n
254+
next[0] = -1
255+
i, j = 2, 0
256+
while i < n:
257+
if t[i - 1] == t[j]:
258+
j += 1
259+
next[i] = j
260+
i += 1
261+
elif j:
262+
j = next[j]
263+
else:
264+
next[i] = 0
265+
i += 1
266+
return s[::-1][: -next[-1]] + s
267+
```
268+
269+
#### Java
270+
271+
```java
272+
class Solution {
273+
public String shortestPalindrome(String s) {
274+
String rev = new StringBuilder(s).reverse().toString();
275+
char[] t = (s + "#" + rev + "$").toCharArray();
276+
int n = t.length;
277+
int[] next = new int[n];
278+
next[0] = -1;
279+
for (int i = 2, j = 0; i < n;) {
280+
if (t[i - 1] == t[j]) {
281+
next[i++] = ++j;
282+
} else if (j > 0) {
283+
j = next[j];
284+
} else {
285+
next[i++] = 0;
286+
}
287+
}
288+
return rev.substring(0, s.length() - next[n - 1]) + s;
289+
}
290+
}
291+
```
292+
293+
#### C++
294+
295+
```cpp
296+
class Solution {
297+
public:
298+
string shortestPalindrome(string s) {
299+
string t = s + "#" + string(s.rbegin(), s.rend()) + "$";
300+
int n = t.size();
301+
int next[n];
302+
next[0] = -1;
303+
next[1] = 0;
304+
for (int i = 2, j = 0; i < n;) {
305+
if (t[i - 1] == t[j]) {
306+
next[i++] = ++j;
307+
} else if (j > 0) {
308+
j = next[j];
309+
} else {
310+
next[i++] = 0;
237311
}
238312
}
313+
return string(s.rbegin(), s.rbegin() + s.size() - next[n - 1]) + s;
314+
}
315+
};
316+
```
317+
318+
#### Go
239319
240-
return string.Empty;
320+
```go
321+
func shortestPalindrome(s string) string {
322+
t := s + "#" + reverse(s) + "$"
323+
n := len(t)
324+
next := make([]int, n)
325+
next[0] = -1
326+
for i, j := 2, 0; i < n; {
327+
if t[i-1] == t[j] {
328+
j++
329+
next[i] = j
330+
i++
331+
} else if j > 0 {
332+
j = next[j]
333+
} else {
334+
next[i] = 0
335+
i++
336+
}
337+
}
338+
return reverse(s)[:len(s)-next[n-1]] + s
339+
}
340+
341+
func reverse(s string) string {
342+
t := []byte(s)
343+
for i, j := 0, len(t)-1; i < j; i, j = i+1, j-1 {
344+
t[i], t[j] = t[j], t[i]
345+
}
346+
return string(t)
347+
}
348+
```
349+
350+
#### TypeScript
351+
352+
```ts
353+
function shortestPalindrome(s: string): string {
354+
const rev = s.split('').reverse().join('');
355+
const t = s + '#' + rev + '$';
356+
const n = t.length;
357+
const next: number[] = Array(n).fill(0);
358+
next[0] = -1;
359+
for (let i = 2, j = 0; i < n; ) {
360+
if (t[i - 1] === t[j]) {
361+
next[i++] = ++j;
362+
} else if (j > 0) {
363+
j = next[j];
364+
} else {
365+
next[i++] = 0;
366+
}
367+
}
368+
return rev.slice(0, -next[n - 1]) + s;
369+
}
370+
```
371+
372+
#### C#
373+
374+
```cs
375+
public class Solution {
376+
public string ShortestPalindrome(string s) {
377+
char[] t = (s + "#" + new string(s.Reverse().ToArray()) + "$").ToCharArray();
378+
int n = t.Length;
379+
int[] next = new int[n];
380+
next[0] = -1;
381+
for (int i = 2, j = 0; i < n;) {
382+
if (t[i - 1] == t[j]) {
383+
next[i++] = ++j;
384+
} else if (j > 0) {
385+
j = next[j];
386+
} else {
387+
next[i++] = 0;
388+
}
389+
}
390+
return new string(s.Substring(next[n - 1]).Reverse().ToArray()).Substring(0, s.Length - next[n - 1]) + s;
241391
}
242392
}
243393
```

‎solution/0200-0299/0214.Shortest Palindrome/README_EN.md

Lines changed: 183 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -182,43 +182,193 @@ impl Solution {
182182
#### C#
183183

184184
```cs
185-
// https://leetcode.com/problems/shortest-palindrome/
186-
187-
using System.Text;
188-
189-
public partial class Solution
190-
{
191-
public string ShortestPalindrome(string s)
192-
{
193-
for (var i = s.Length - 1; i >= 0; --i)
194-
{
195-
var k = i;
196-
var j = 0;
197-
while (j < k)
198-
{
199-
if (s[j] == s[k])
200-
{
201-
++j;
202-
--k;
203-
}
204-
else
205-
{
206-
break;
207-
}
185+
public class Solution {
186+
public string ShortestPalindrome(string s) {
187+
int baseValue = 131;
188+
int mul = 1;
189+
int mod = (int)1e9 + 7;
190+
int prefix = 0, suffix = 0;
191+
int idx = 0;
192+
int n = s.Length;
193+
194+
for (int i = 0; i < n; ++i) {
195+
int t = s[i] - 'a' + 1;
196+
prefix = (int)(((long)prefix * baseValue + t) % mod);
197+
suffix = (int)((suffix + (long)t * mul) % mod);
198+
mul = (int)(((long)mul * baseValue) % mod);
199+
if (prefix == suffix) {
200+
idx = i + 1;
208201
}
209-
if (j >= k)
210-
{
211-
var sb = new StringBuilder(s.Length * 2 - i - 1);
212-
for (var l = s.Length - 1; l >= i + 1; --l)
213-
{
214-
sb.Append(s[l]);
215-
}
216-
sb.Append(s);
217-
return sb.ToString();
202+
}
203+
204+
if (idx == n) {
205+
return s;
206+
}
207+
208+
return new string(s.Substring(idx).Reverse().ToArray()) + s;
209+
}
210+
}
211+
```
212+
213+
<!-- tabs:end -->
214+
215+
<!-- solution:end -->
216+
217+
<!-- solution:start -->
218+
219+
### Solution 2: KMP Algorithm
220+
221+
According to the problem description, we need to reverse the string $s$ to obtain the string $\textit{rev}$, and then find the longest common part of the suffix of the string $\textit{rev}$ and the prefix of the string $s$. We can use the KMP algorithm to concatenate the string $s$ and the string $\textit{rev}$ and find the longest common part of the longest prefix and the longest suffix.
222+
223+
The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string $s$.
224+
225+
<!-- tabs:start -->
226+
227+
#### Python3
228+
229+
```python
230+
class Solution:
231+
def shortestPalindrome(self, s: str) -> str:
232+
t = s + "#" + s[::-1] + "$"
233+
n = len(t)
234+
next = [0] * n
235+
next[0] = -1
236+
i, j = 2, 0
237+
while i < n:
238+
if t[i - 1] == t[j]:
239+
j += 1
240+
next[i] = j
241+
i += 1
242+
elif j:
243+
j = next[j]
244+
else:
245+
next[i] = 0
246+
i += 1
247+
return s[::-1][: -next[-1]] + s
248+
```
249+
250+
#### Java
251+
252+
```java
253+
class Solution {
254+
public String shortestPalindrome(String s) {
255+
String rev = new StringBuilder(s).reverse().toString();
256+
char[] t = (s + "#" + rev + "$").toCharArray();
257+
int n = t.length;
258+
int[] next = new int[n];
259+
next[0] = -1;
260+
for (int i = 2, j = 0; i < n;) {
261+
if (t[i - 1] == t[j]) {
262+
next[i++] = ++j;
263+
} else if (j > 0) {
264+
j = next[j];
265+
} else {
266+
next[i++] = 0;
267+
}
268+
}
269+
return rev.substring(0, s.length() - next[n - 1]) + s;
270+
}
271+
}
272+
```
273+
274+
#### C++
275+
276+
```cpp
277+
class Solution {
278+
public:
279+
string shortestPalindrome(string s) {
280+
string t = s + "#" + string(s.rbegin(), s.rend()) + "$";
281+
int n = t.size();
282+
int next[n];
283+
next[0] = -1;
284+
next[1] = 0;
285+
for (int i = 2, j = 0; i < n;) {
286+
if (t[i - 1] == t[j]) {
287+
next[i++] = ++j;
288+
} else if (j > 0) {
289+
j = next[j];
290+
} else {
291+
next[i++] = 0;
218292
}
219293
}
294+
return string(s.rbegin(), s.rbegin() + s.size() - next[n - 1]) + s;
295+
}
296+
};
297+
```
298+
299+
#### Go
220300
221-
return string.Empty;
301+
```go
302+
func shortestPalindrome(s string) string {
303+
t := s + "#" + reverse(s) + "$"
304+
n := len(t)
305+
next := make([]int, n)
306+
next[0] = -1
307+
for i, j := 2, 0; i < n; {
308+
if t[i-1] == t[j] {
309+
j++
310+
next[i] = j
311+
i++
312+
} else if j > 0 {
313+
j = next[j]
314+
} else {
315+
next[i] = 0
316+
i++
317+
}
318+
}
319+
return reverse(s)[:len(s)-next[n-1]] + s
320+
}
321+
322+
func reverse(s string) string {
323+
t := []byte(s)
324+
for i, j := 0, len(t)-1; i < j; i, j = i+1, j-1 {
325+
t[i], t[j] = t[j], t[i]
326+
}
327+
return string(t)
328+
}
329+
```
330+
331+
#### TypeScript
332+
333+
```ts
334+
function shortestPalindrome(s: string): string {
335+
const rev = s.split('').reverse().join('');
336+
const t = s + '#' + rev + '$';
337+
const n = t.length;
338+
const next: number[] = Array(n).fill(0);
339+
next[0] = -1;
340+
for (let i = 2, j = 0; i < n; ) {
341+
if (t[i - 1] === t[j]) {
342+
next[i++] = ++j;
343+
} else if (j > 0) {
344+
j = next[j];
345+
} else {
346+
next[i++] = 0;
347+
}
348+
}
349+
return rev.slice(0, -next[n - 1]) + s;
350+
}
351+
```
352+
353+
#### C#
354+
355+
```cs
356+
public class Solution {
357+
public string ShortestPalindrome(string s) {
358+
char[] t = (s + "#" + new string(s.Reverse().ToArray()) + "$").ToCharArray();
359+
int n = t.Length;
360+
int[] next = new int[n];
361+
next[0] = -1;
362+
for (int i = 2, j = 0; i < n;) {
363+
if (t[i - 1] == t[j]) {
364+
next[i++] = ++j;
365+
} else if (j > 0) {
366+
j = next[j];
367+
} else {
368+
next[i++] = 0;
369+
}
370+
}
371+
return new string(s.Substring(next[n - 1]).Reverse().ToArray()).Substring(0, s.Length - next[n - 1]) + s;
222372
}
223373
}
224374
```
Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,26 @@
1-
// https://leetcode.com/problems/shortest-palindrome/
1+
public class Solution {
2+
public string ShortestPalindrome(string s) {
3+
int baseValue = 131;
4+
int mul = 1;
5+
int mod = (int)1e9 + 7;
6+
int prefix = 0, suffix = 0;
7+
int idx = 0;
8+
int n = s.Length;
29

3-
using System.Text;
4-
5-
public partial class Solution
6-
{
7-
public string ShortestPalindrome(string s)
8-
{
9-
for (var i = s.Length - 1; i >= 0; --i)
10-
{
11-
var k = i;
12-
var j = 0;
13-
while (j < k)
14-
{
15-
if (s[j] == s[k])
16-
{
17-
++j;
18-
--k;
19-
}
20-
else
21-
{
22-
break;
23-
}
24-
}
25-
if (j >= k)
26-
{
27-
var sb = new StringBuilder(s.Length * 2 - i - 1);
28-
for (var l = s.Length - 1; l >= i + 1; --l)
29-
{
30-
sb.Append(s[l]);
31-
}
32-
sb.Append(s);
33-
return sb.ToString();
10+
for (int i = 0; i < n; ++i) {
11+
int t = s[i] - 'a' + 1;
12+
prefix = (int)(((long)prefix * baseValue + t) % mod);
13+
suffix = (int)((suffix + (long)t * mul) % mod);
14+
mul = (int)(((long)mul * baseValue) % mod);
15+
if (prefix == suffix) {
16+
idx = i + 1;
3417
}
3518
}
3619

37-
return string.Empty;
20+
if (idx == n) {
21+
return s;
22+
}
23+
24+
return new string(s.Substring(idx).Reverse().ToArray()) + s;
3825
}
39-
}
26+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class Solution {
2+
public:
3+
string shortestPalindrome(string s) {
4+
string t = s + "#" + string(s.rbegin(), s.rend()) + "$";
5+
int n = t.size();
6+
int next[n];
7+
next[0] = -1;
8+
next[1] = 0;
9+
for (int i = 2, j = 0; i < n;) {
10+
if (t[i - 1] == t[j]) {
11+
next[i++] = ++j;
12+
} else if (j > 0) {
13+
j = next[j];
14+
} else {
15+
next[i++] = 0;
16+
}
17+
}
18+
return string(s.rbegin(), s.rbegin() + s.size() - next[n - 1]) + s;
19+
}
20+
};
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
public class Solution {
2+
public string ShortestPalindrome(string s) {
3+
char[] t = (s + "#" + new string(s.Reverse().ToArray()) + "$").ToCharArray();
4+
int n = t.Length;
5+
int[] next = new int[n];
6+
next[0] = -1;
7+
for (int i = 2, j = 0; i < n;) {
8+
if (t[i - 1] == t[j]) {
9+
next[i++] = ++j;
10+
} else if (j > 0) {
11+
j = next[j];
12+
} else {
13+
next[i++] = 0;
14+
}
15+
}
16+
return new string(s.Substring(next[n - 1]).Reverse().ToArray()).Substring(0, s.Length - next[n - 1]) + s;
17+
}
18+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
func shortestPalindrome(s string) string {
2+
t := s + "#" + reverse(s) + "$"
3+
n := len(t)
4+
next := make([]int, n)
5+
next[0] = -1
6+
for i, j := 2, 0; i < n; {
7+
if t[i-1] == t[j] {
8+
j++
9+
next[i] = j
10+
i++
11+
} else if j > 0 {
12+
j = next[j]
13+
} else {
14+
next[i] = 0
15+
i++
16+
}
17+
}
18+
return reverse(s)[:len(s)-next[n-1]] + s
19+
}
20+
21+
func reverse(s string) string {
22+
t := []byte(s)
23+
for i, j := 0, len(t)-1; i < j; i, j = i+1, j-1 {
24+
t[i], t[j] = t[j], t[i]
25+
}
26+
return string(t)
27+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
class Solution {
2+
public String shortestPalindrome(String s) {
3+
String rev = new StringBuilder(s).reverse().toString();
4+
char[] t = (s + "#" + rev + "$").toCharArray();
5+
int n = t.length;
6+
int[] next = new int[n];
7+
next[0] = -1;
8+
for (int i = 2, j = 0; i < n;) {
9+
if (t[i - 1] == t[j]) {
10+
next[i++] = ++j;
11+
} else if (j > 0) {
12+
j = next[j];
13+
} else {
14+
next[i++] = 0;
15+
}
16+
}
17+
return rev.substring(0, s.length() - next[n - 1]) + s;
18+
}
19+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class Solution:
2+
def shortestPalindrome(self, s: str) -> str:
3+
t = s + "#" + s[::-1] + "$"
4+
n = len(t)
5+
next = [0] * n
6+
next[0] = -1
7+
i, j = 2, 0
8+
while i < n:
9+
if t[i - 1] == t[j]:
10+
j += 1
11+
next[i] = j
12+
i += 1
13+
elif j:
14+
j = next[j]
15+
else:
16+
next[i] = 0
17+
i += 1
18+
return s[::-1][: -next[-1]] + s
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function shortestPalindrome(s: string): string {
2+
const rev = s.split('').reverse().join('');
3+
const t = s + '#' + rev + '$';
4+
const n = t.length;
5+
const next: number[] = Array(n).fill(0);
6+
next[0] = -1;
7+
for (let i = 2, j = 0; i < n; ) {
8+
if (t[i - 1] === t[j]) {
9+
next[i++] = ++j;
10+
} else if (j > 0) {
11+
j = next[j];
12+
} else {
13+
next[i++] = 0;
14+
}
15+
}
16+
return rev.slice(0, -next[n - 1]) + s;
17+
}

0 commit comments

Comments
 (0)
Please sign in to comment.